| /* |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.bluetooth.hfp; |
| |
| import org.junit.After; |
| import org.junit.Assert; |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.Mock; |
| import org.mockito.MockitoAnnotations; |
| |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.Mockito.*; |
| |
| import android.bluetooth.BluetoothAdapter; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.net.Uri; |
| import android.os.Binder; |
| import android.os.IBinder; |
| import android.telecom.Call; |
| import android.telecom.Connection; |
| import android.telecom.GatewayInfo; |
| import android.telecom.PhoneAccount; |
| import android.telecom.PhoneAccountHandle; |
| import android.telecom.TelecomManager; |
| import android.telephony.PhoneNumberUtils; |
| import android.telephony.TelephonyManager; |
| import android.util.Log; |
| |
| import androidx.test.core.app.ApplicationProvider; |
| import androidx.test.rule.ServiceTestRule; |
| import androidx.test.filters.MediumTest; |
| import androidx.test.runner.AndroidJUnit4; |
| |
| import java.util.ArrayList; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.UUID; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * Tests for {@link BluetoothInCallService} |
| */ |
| @MediumTest |
| @RunWith(AndroidJUnit4.class) |
| public class BluetoothInCallServiceTest { |
| |
| private static final int TEST_DTMF_TONE = 0; |
| private static final String TEST_ACCOUNT_ADDRESS = "//foo.com/"; |
| private static final int TEST_ACCOUNT_INDEX = 0; |
| |
| private static final int CALL_STATE_ACTIVE = 0; |
| private static final int CALL_STATE_HELD = 1; |
| private static final int CALL_STATE_DIALING = 2; |
| private static final int CALL_STATE_ALERTING = 3; |
| private static final int CALL_STATE_INCOMING = 4; |
| private static final int CALL_STATE_WAITING = 5; |
| private static final int CALL_STATE_IDLE = 6; |
| private static final int CALL_STATE_DISCONNECTED = 7; |
| // Terminate all held or set UDUB("busy") to a waiting call |
| private static final int CHLD_TYPE_RELEASEHELD = 0; |
| // Terminate all active calls and accepts a waiting/held call |
| private static final int CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD = 1; |
| // Hold all active calls and accepts a waiting/held call |
| private static final int CHLD_TYPE_HOLDACTIVE_ACCEPTHELD = 2; |
| // Add all held calls to a conference |
| private static final int CHLD_TYPE_ADDHELDTOCONF = 3; |
| |
| private TestableBluetoothInCallService mBluetoothInCallService; |
| @Rule public final ServiceTestRule mServiceRule |
| = ServiceTestRule.withTimeout(1, TimeUnit.SECONDS); |
| |
| @Mock private BluetoothHeadsetProxy mMockBluetoothHeadset; |
| @Mock private BluetoothInCallService.CallInfo mMockCallInfo; |
| @Mock private TelephonyManager mMockTelephonyManager; |
| |
| public class TestableBluetoothInCallService extends BluetoothInCallService { |
| @Override |
| public IBinder onBind(Intent intent) { |
| IBinder binder = super.onBind(intent); |
| IntentFilter intentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); |
| registerReceiver(mBluetoothAdapterReceiver, intentFilter); |
| mTelephonyManager = getSystemService(TelephonyManager.class); |
| mTelecomManager = getSystemService(TelecomManager.class); |
| return binder; |
| } |
| @Override |
| protected void enforceModifyPermission() {} |
| } |
| |
| @Before |
| public void setUp() throws Exception { |
| MockitoAnnotations.initMocks(this); |
| |
| // Create the service Intent. |
| Intent serviceIntent = |
| new Intent(ApplicationProvider.getApplicationContext(), |
| TestableBluetoothInCallService.class); |
| // Bind the service |
| mServiceRule.bindService(serviceIntent); |
| |
| // Ensure initialization does not actually try to access any of the CallsManager fields. |
| // This also works to return null if it is not overwritten later in the test. |
| doReturn(null).when(mMockCallInfo).getActiveCall(); |
| doReturn(null).when(mMockCallInfo) |
| .getRingingOrSimulatedRingingCall(); |
| doReturn(null).when(mMockCallInfo).getHeldCall(); |
| doReturn(null).when(mMockCallInfo).getOutgoingCall(); |
| doReturn(0).when(mMockCallInfo).getNumHeldCalls(); |
| doReturn(false).when(mMockCallInfo).hasOnlyDisconnectedCalls(); |
| doReturn(true).when(mMockCallInfo).isNullCall(null); |
| doReturn(false).when(mMockCallInfo).isNullCall(notNull()); |
| |
| mBluetoothInCallService = new TestableBluetoothInCallService(); |
| mBluetoothInCallService.setBluetoothHeadset(mMockBluetoothHeadset); |
| mBluetoothInCallService.mCallInfo = mMockCallInfo; |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| mServiceRule.unbindService(); |
| mBluetoothInCallService = null; |
| } |
| |
| @Test |
| public void testHeadsetAnswerCall() throws Exception { |
| BluetoothCall mockCall = createRingingCall(); |
| |
| boolean callAnswered = mBluetoothInCallService.answerCall(); |
| verify(mockCall).answer(any(int.class)); |
| |
| Assert.assertTrue(callAnswered); |
| } |
| |
| @Test |
| public void testHeadsetAnswerCallNull() throws Exception { |
| when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(null); |
| |
| boolean callAnswered = mBluetoothInCallService.answerCall(); |
| Assert.assertFalse(callAnswered); |
| } |
| |
| @Test |
| public void testHeadsetHangupCall() throws Exception { |
| BluetoothCall mockCall = createForegroundCall(); |
| |
| boolean callHungup = mBluetoothInCallService.hangupCall(); |
| |
| verify(mockCall).disconnect(); |
| Assert.assertTrue(callHungup); |
| } |
| |
| @Test |
| public void testHeadsetHangupCallNull() throws Exception { |
| when(mMockCallInfo.getForegroundCall()).thenReturn(null); |
| |
| boolean callHungup = mBluetoothInCallService.hangupCall(); |
| Assert.assertFalse(callHungup); |
| } |
| |
| @Test |
| public void testHeadsetSendDTMF() throws Exception { |
| BluetoothCall mockCall = createForegroundCall(); |
| |
| boolean sentDtmf = mBluetoothInCallService.sendDtmf(TEST_DTMF_TONE); |
| |
| verify(mockCall).playDtmfTone(eq((char) TEST_DTMF_TONE)); |
| verify(mockCall).stopDtmfTone(); |
| Assert.assertTrue(sentDtmf); |
| } |
| |
| @Test |
| public void testHeadsetSendDTMFNull() throws Exception { |
| when(mMockCallInfo.getForegroundCall()).thenReturn(null); |
| |
| boolean sentDtmf = mBluetoothInCallService.sendDtmf(TEST_DTMF_TONE); |
| Assert.assertFalse(sentDtmf); |
| } |
| |
| @Test |
| public void testGetNetworkOperator() throws Exception { |
| PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX); |
| when(mMockCallInfo.getBestPhoneAccount()).thenReturn(fakePhoneAccount); |
| |
| String networkOperator = mBluetoothInCallService.getNetworkOperator(); |
| Assert.assertEquals(networkOperator, "label0"); |
| } |
| |
| @Test |
| public void testGetNetworkOperatorNoPhoneAccount() throws Exception { |
| when(mMockCallInfo.getForegroundCall()).thenReturn(null); |
| when(mMockTelephonyManager.getNetworkOperatorName()).thenReturn("label1"); |
| mBluetoothInCallService.mTelephonyManager = mMockTelephonyManager; |
| |
| String networkOperator = mBluetoothInCallService.getNetworkOperator(); |
| Assert.assertEquals(networkOperator, "label1"); |
| } |
| |
| @Test |
| public void testGetSubscriberNumber() throws Exception { |
| PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX); |
| when(mMockCallInfo.getBestPhoneAccount()).thenReturn(fakePhoneAccount); |
| |
| String subscriberNumber = mBluetoothInCallService.getSubscriberNumber(); |
| Assert.assertEquals(subscriberNumber, TEST_ACCOUNT_ADDRESS + TEST_ACCOUNT_INDEX); |
| } |
| |
| @Test |
| public void testGetSubscriberNumberFallbackToTelephony() throws Exception { |
| String fakeNumber = "8675309"; |
| when(mMockCallInfo.getBestPhoneAccount()).thenReturn(null); |
| when(mMockTelephonyManager.getLine1Number()) |
| .thenReturn(fakeNumber); |
| mBluetoothInCallService.mTelephonyManager = mMockTelephonyManager; |
| |
| String subscriberNumber = mBluetoothInCallService.getSubscriberNumber(); |
| Assert.assertEquals(subscriberNumber, fakeNumber); |
| } |
| |
| @Test |
| public void testListCurrentCallsOneCall() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| BluetoothCall activeCall = createActiveCall(); |
| when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE); |
| calls.add(activeCall); |
| mBluetoothInCallService.onCallAdded(activeCall); |
| when(activeCall.isConference()).thenReturn(false); |
| when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-000")); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| |
| verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(0), eq(0), eq(false), |
| eq("555000"), eq(PhoneNumberUtils.TOA_Unknown)); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| } |
| |
| @Test |
| public void testListCurrentCallsSilentRinging() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| BluetoothCall silentRingingCall = createActiveCall(); |
| when(silentRingingCall.getState()).thenReturn(Call.STATE_RINGING); |
| when(silentRingingCall.isSilentRingingRequested()).thenReturn(true); |
| calls.add(silentRingingCall); |
| mBluetoothInCallService.onCallAdded(silentRingingCall); |
| |
| when(silentRingingCall.isConference()).thenReturn(false); |
| when(silentRingingCall.getHandle()).thenReturn(Uri.parse("tel:555-000")); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(silentRingingCall); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| |
| verify(mMockBluetoothHeadset, never()).clccResponse(eq(1), eq(0), eq(0), eq(0), eq(false), |
| eq("555000"), eq(PhoneNumberUtils.TOA_Unknown)); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| } |
| |
| @Test |
| public void testConferenceInProgressCDMA() throws Exception { |
| // If two calls are being conferenced and updateHeadsetWithCallState runs while this is |
| // still occurring, it will look like there is an active and held BluetoothCall still while |
| // we are transitioning into a conference. |
| // BluetoothCall has been put into a CDMA "conference" with one BluetoothCall on hold. |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| BluetoothCall parentCall = createActiveCall(); |
| final BluetoothCall confCall1 = getMockCall(); |
| final BluetoothCall confCall2 = createHeldCall(); |
| calls.add(parentCall); |
| calls.add(confCall1); |
| calls.add(confCall2); |
| mBluetoothInCallService.onCallAdded(parentCall); |
| mBluetoothInCallService.onCallAdded(confCall1); |
| mBluetoothInCallService.onCallAdded(confCall2); |
| |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| when(confCall1.getState()).thenReturn(Call.STATE_ACTIVE); |
| when(confCall2.getState()).thenReturn(Call.STATE_ACTIVE); |
| when(confCall1.isIncoming()).thenReturn(false); |
| when(confCall2.isIncoming()).thenReturn(true); |
| when(confCall1.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0000"))); |
| when(confCall2.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0001"))); |
| addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE); |
| addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE); |
| removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); |
| String confCall1Id = confCall1.getTelecomCallId(); |
| when(parentCall.getGenericConferenceActiveChildCallId()) |
| .thenReturn(confCall1Id); |
| when(parentCall.isConference()).thenReturn(true); |
| List<String> childrenIds = new LinkedList<String>(){{ |
| add(confCall1.getTelecomCallId()); |
| add(confCall2.getTelecomCallId()); |
| }}; |
| when(parentCall.getChildrenIds()).thenReturn(childrenIds); |
| //Add links from child calls to parent |
| String parentId = parentCall.getTelecomCallId(); |
| when(confCall1.getParentId()).thenReturn(parentId); |
| when(confCall2.getParentId()).thenReturn(parentId); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.queryPhoneState(); |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| |
| when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true); |
| List<BluetoothCall> children = |
| mBluetoothInCallService.getBluetoothCallsByIds(parentCall.getChildrenIds()); |
| mBluetoothInCallService.getCallback(parentCall) |
| .onChildrenChanged(parentCall, children); |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| |
| when(mMockCallInfo.getHeldCall()).thenReturn(null); |
| // Spurious BluetoothCall to onIsConferencedChanged. |
| mBluetoothInCallService.getCallback(parentCall) |
| .onChildrenChanged(parentCall, children); |
| // Make sure the BluetoothCall has only occurred collectively 2 times (not on the third) |
| verify(mMockBluetoothHeadset, times(2)).phoneStateChanged(any(int.class), |
| any(int.class), any(int.class), nullable(String.class), any(int.class), |
| nullable(String.class)); |
| } |
| |
| @Test |
| public void testListCurrentCallsCdmaHold() throws Exception { |
| // BluetoothCall has been put into a CDMA "conference" with one BluetoothCall on hold. |
| List<BluetoothCall> calls = new ArrayList<BluetoothCall>(); |
| BluetoothCall parentCall = createActiveCall(); |
| final BluetoothCall foregroundCall = getMockCall(); |
| final BluetoothCall heldCall = createHeldCall(); |
| calls.add(parentCall); |
| calls.add(foregroundCall); |
| calls.add(heldCall); |
| mBluetoothInCallService.onCallAdded(parentCall); |
| mBluetoothInCallService.onCallAdded(foregroundCall); |
| mBluetoothInCallService.onCallAdded(heldCall); |
| |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| when(foregroundCall.getState()).thenReturn(Call.STATE_ACTIVE); |
| when(heldCall.getState()).thenReturn(Call.STATE_ACTIVE); |
| when(foregroundCall.isIncoming()).thenReturn(false); |
| when(heldCall.isIncoming()).thenReturn(true); |
| when(foregroundCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0000"))); |
| when(heldCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0001"))); |
| addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE); |
| addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE); |
| removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); |
| |
| String foregroundCallId = foregroundCall.getTelecomCallId(); |
| when(parentCall.getGenericConferenceActiveChildCallId()).thenReturn(foregroundCallId); |
| when(parentCall.isConference()).thenReturn(true); |
| List<String> childrenIds = new LinkedList<String>(){{ |
| add(foregroundCall.getTelecomCallId()); |
| add(heldCall.getTelecomCallId()); |
| }}; |
| when(parentCall.getChildrenIds()).thenReturn(childrenIds); |
| //Add links from child calls to parent |
| String parentId = parentCall.getTelecomCallId(); |
| when(foregroundCall.getParentId()).thenReturn(parentId); |
| when(heldCall.getParentId()).thenReturn(parentId); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| |
| verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0), |
| eq(false), eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown)); |
| verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_HELD), eq(0), |
| eq(false), eq("5550001"), eq(PhoneNumberUtils.TOA_Unknown)); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| } |
| |
| @Test |
| public void testListCurrentCallsCdmaConference() throws Exception { |
| // BluetoothCall is in a true CDMA conference |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| BluetoothCall parentCall = createActiveCall(); |
| final BluetoothCall confCall1 = getMockCall(); |
| final BluetoothCall confCall2 = createHeldCall(); |
| calls.add(parentCall); |
| calls.add(confCall1); |
| calls.add(confCall2); |
| mBluetoothInCallService.onCallAdded(parentCall); |
| mBluetoothInCallService.onCallAdded(confCall1); |
| mBluetoothInCallService.onCallAdded(confCall2); |
| |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| when(confCall1.getState()).thenReturn(Call.STATE_ACTIVE); |
| when(confCall2.getState()).thenReturn(Call.STATE_ACTIVE); |
| when(confCall1.isIncoming()).thenReturn(false); |
| when(confCall2.isIncoming()).thenReturn(true); |
| when(confCall1.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0000"))); |
| when(confCall2.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0001"))); |
| removeCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE); |
| removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); |
| when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true); |
| //when(parentCall.getConferenceLevelActiveCall()).thenReturn(confCall1); |
| when(parentCall.isConference()).thenReturn(true); |
| List<String> childrenIds = new LinkedList<String>(){{ |
| add(confCall1.getTelecomCallId()); |
| add(confCall2.getTelecomCallId()); |
| }}; |
| when(parentCall.getChildrenIds()).thenReturn(childrenIds); |
| //Add links from child calls to parent |
| String parentId = parentCall.getTelecomCallId(); |
| when(confCall1.getParentId()).thenReturn(parentId); |
| when(confCall2.getParentId()).thenReturn(parentId); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| |
| verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0), |
| eq(true), eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown)); |
| verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_ACTIVE), eq(0), |
| eq(true), eq("5550001"), eq(PhoneNumberUtils.TOA_Unknown)); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| } |
| |
| @Test |
| public void testWaitingCallClccResponse() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| // This test does not define a value for getForegroundCall(), so this ringing |
| // BluetoothCall will be treated as if it is a waiting BluetoothCall |
| // when listCurrentCalls() is invoked. |
| BluetoothCall waitingCall = createRingingCall(); |
| calls.add(waitingCall); |
| mBluetoothInCallService.onCallAdded(waitingCall); |
| |
| when(waitingCall.isIncoming()).thenReturn(true); |
| when(waitingCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0000"))); |
| when(waitingCall.getState()).thenReturn(Call.STATE_RINGING); |
| when(waitingCall.isConference()).thenReturn(false); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_WAITING, 0, false, |
| "5550000", PhoneNumberUtils.TOA_Unknown); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(), |
| anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt()); |
| } |
| |
| @Test |
| public void testNewCallClccResponse() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| BluetoothCall newCall = createForegroundCall(); |
| calls.add(newCall); |
| mBluetoothInCallService.onCallAdded(newCall); |
| |
| when(newCall.getState()).thenReturn(Call.STATE_NEW); |
| when(newCall.isConference()).thenReturn(false); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| verify(mMockBluetoothHeadset, times(1)).clccResponse(anyInt(), |
| anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt()); |
| } |
| |
| @Test |
| public void testRingingCallClccResponse() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| BluetoothCall ringingCall = createForegroundCall(); |
| calls.add(ringingCall); |
| mBluetoothInCallService.onCallAdded(ringingCall); |
| |
| when(ringingCall.getState()).thenReturn(Call.STATE_RINGING); |
| when(ringingCall.isIncoming()).thenReturn(true); |
| when(ringingCall.isConference()).thenReturn(false); |
| when(ringingCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0000"))); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false, |
| "5550000", PhoneNumberUtils.TOA_Unknown); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(), |
| anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt()); |
| } |
| |
| @Test |
| public void testCallClccCache() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| BluetoothCall ringingCall = createForegroundCall(); |
| calls.add(ringingCall); |
| mBluetoothInCallService.onCallAdded(ringingCall); |
| |
| when(ringingCall.getState()).thenReturn(Call.STATE_RINGING); |
| when(ringingCall.isIncoming()).thenReturn(true); |
| when(ringingCall.isConference()).thenReturn(false); |
| when(ringingCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:5550000"))); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false, |
| "5550000", PhoneNumberUtils.TOA_Unknown); |
| |
| // Test Caching of old BluetoothCall indices in clcc |
| when(ringingCall.getState()).thenReturn(Call.STATE_ACTIVE); |
| BluetoothCall newHoldingCall = createHeldCall(); |
| calls.add(0, newHoldingCall); |
| mBluetoothInCallService.onCallAdded(newHoldingCall); |
| |
| when(newHoldingCall.getState()).thenReturn(Call.STATE_HOLDING); |
| when(newHoldingCall.isIncoming()).thenReturn(true); |
| when(newHoldingCall.isConference()).thenReturn(false); |
| when(newHoldingCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0001"))); |
| |
| mBluetoothInCallService.listCurrentCalls(); |
| verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_ACTIVE, 0, false, |
| "5550000", PhoneNumberUtils.TOA_Unknown); |
| verify(mMockBluetoothHeadset).clccResponse(2, 1, CALL_STATE_HELD, 0, false, |
| "5550001", PhoneNumberUtils.TOA_Unknown); |
| verify(mMockBluetoothHeadset, times(2)).clccResponse(0, 0, 0, 0, false, null, 0); |
| } |
| |
| @Test |
| public void testAlertingCallClccResponse() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| BluetoothCall dialingCall = createForegroundCall(); |
| calls.add(dialingCall); |
| mBluetoothInCallService.onCallAdded(dialingCall); |
| |
| when(dialingCall.getState()).thenReturn(Call.STATE_DIALING); |
| when(dialingCall.isIncoming()).thenReturn(false); |
| when(dialingCall.isConference()).thenReturn(false); |
| when(dialingCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0000"))); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| verify(mMockBluetoothHeadset).clccResponse(1, 0, CALL_STATE_ALERTING, 0, false, |
| "5550000", PhoneNumberUtils.TOA_Unknown); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(), |
| anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt()); |
| } |
| |
| @Test |
| public void testHoldingCallClccResponse() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| BluetoothCall dialingCall = createForegroundCall(); |
| calls.add(dialingCall); |
| mBluetoothInCallService.onCallAdded(dialingCall); |
| |
| when(dialingCall.getState()).thenReturn(Call.STATE_DIALING); |
| when(dialingCall.isIncoming()).thenReturn(false); |
| when(dialingCall.isConference()).thenReturn(false); |
| when(dialingCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0000"))); |
| BluetoothCall holdingCall = createHeldCall(); |
| calls.add(holdingCall); |
| mBluetoothInCallService.onCallAdded(holdingCall); |
| |
| when(holdingCall.getState()).thenReturn(Call.STATE_HOLDING); |
| when(holdingCall.isIncoming()).thenReturn(true); |
| when(holdingCall.isConference()).thenReturn(false); |
| when(holdingCall.getGatewayInfo()).thenReturn( |
| new GatewayInfo(null, null, Uri.parse("tel:555-0001"))); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| verify(mMockBluetoothHeadset).clccResponse(1, 0, CALL_STATE_ALERTING, 0, false, |
| "5550000", PhoneNumberUtils.TOA_Unknown); |
| verify(mMockBluetoothHeadset).clccResponse(2, 1, CALL_STATE_HELD, 0, false, |
| "5550001", PhoneNumberUtils.TOA_Unknown); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| verify(mMockBluetoothHeadset, times(3)).clccResponse(anyInt(), |
| anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt()); |
| } |
| |
| @Test |
| public void testListCurrentCallsImsConference() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| BluetoothCall parentCall = createActiveCall(); |
| calls.add(parentCall); |
| mBluetoothInCallService.onCallAdded(parentCall); |
| |
| addCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); |
| when(parentCall.isConference()).thenReturn(true); |
| when(parentCall.getState()).thenReturn(Call.STATE_ACTIVE); |
| when(parentCall.isIncoming()).thenReturn(true); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| |
| verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(1), eq(CALL_STATE_ACTIVE), eq(0), |
| eq(true), (String) isNull(), eq(-1)); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| } |
| |
| @Test |
| public void testListCurrentCallsHeldImsCepConference() throws Exception { |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| BluetoothCall parentCall = createHeldCall(); |
| BluetoothCall childCall1 = createActiveCall(); |
| BluetoothCall childCall2 = createActiveCall(); |
| calls.add(parentCall); |
| calls.add(childCall1); |
| calls.add(childCall2); |
| mBluetoothInCallService.onCallAdded(parentCall); |
| mBluetoothInCallService.onCallAdded(childCall1); |
| mBluetoothInCallService.onCallAdded(childCall2); |
| |
| addCallCapability(parentCall, Connection.CAPABILITY_MANAGE_CONFERENCE); |
| String parentId = parentCall.getTelecomCallId(); |
| when(childCall1.getParentId()).thenReturn(parentId); |
| when(childCall2.getParentId()).thenReturn(parentId); |
| |
| when(parentCall.isConference()).thenReturn(true); |
| when(parentCall.getState()).thenReturn(Call.STATE_HOLDING); |
| when(childCall1.getState()).thenReturn(Call.STATE_ACTIVE); |
| when(childCall2.getState()).thenReturn(Call.STATE_ACTIVE); |
| |
| when(parentCall.isIncoming()).thenReturn(true); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.listCurrentCalls(); |
| |
| verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_HELD), eq(0), |
| eq(true), (String) isNull(), eq(-1)); |
| verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(0), eq(CALL_STATE_HELD), eq(0), |
| eq(true), (String) isNull(), eq(-1)); |
| verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); |
| } |
| |
| @Test |
| public void testQueryPhoneState() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:5550000")); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.queryPhoneState(); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), |
| eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class)); |
| } |
| |
| @Test |
| public void testCDMAConferenceQueryState() throws Exception { |
| BluetoothCall parentConfCall = createActiveCall(); |
| final BluetoothCall confCall1 = getMockCall(); |
| final BluetoothCall confCall2 = getMockCall(); |
| mBluetoothInCallService.onCallAdded(confCall1); |
| mBluetoothInCallService.onCallAdded(confCall2); |
| when(parentConfCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); |
| addCallCapability(parentConfCall, Connection.CAPABILITY_SWAP_CONFERENCE); |
| removeCallCapability(parentConfCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); |
| when(parentConfCall.wasConferencePreviouslyMerged()).thenReturn(true); |
| when(parentConfCall.isConference()).thenReturn(true); |
| List<String> childrenIds = new LinkedList<String>(){{ |
| add(confCall1.getTelecomCallId()); |
| add(confCall2.getTelecomCallId()); |
| }}; |
| when(parentConfCall.getChildrenIds()).thenReturn(childrenIds); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.queryPhoneState(); |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testProcessChldTypeReleaseHeldRinging() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| Log.i("BluetoothInCallService", "asdf start " + Integer.toString(ringingCall.hashCode())); |
| |
| boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_RELEASEHELD); |
| |
| verify(ringingCall).reject(eq(false), nullable(String.class)); |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldTypeReleaseHeldHold() throws Exception { |
| BluetoothCall onHoldCall = createHeldCall(); |
| boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_RELEASEHELD); |
| |
| verify(onHoldCall).disconnect(); |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldReleaseActiveRinging() throws Exception { |
| BluetoothCall activeCall = createActiveCall(); |
| BluetoothCall ringingCall = createRingingCall(); |
| |
| boolean didProcess = mBluetoothInCallService.processChld( |
| CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD); |
| |
| verify(activeCall).disconnect(); |
| verify(ringingCall).answer(any(int.class)); |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldReleaseActiveHold() throws Exception { |
| BluetoothCall activeCall = createActiveCall(); |
| BluetoothCall heldCall = createHeldCall(); |
| |
| boolean didProcess = mBluetoothInCallService.processChld( |
| CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD); |
| |
| verify(activeCall).disconnect(); |
| // BluetoothCall unhold will occur as part of CallsManager auto-unholding |
| // the background BluetoothCall on its own. |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldHoldActiveRinging() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| |
| boolean didProcess = mBluetoothInCallService.processChld( |
| CHLD_TYPE_HOLDACTIVE_ACCEPTHELD); |
| |
| verify(ringingCall).answer(any(int.class)); |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldHoldActiveUnhold() throws Exception { |
| BluetoothCall heldCall = createHeldCall(); |
| |
| boolean didProcess = mBluetoothInCallService.processChld( |
| CHLD_TYPE_HOLDACTIVE_ACCEPTHELD); |
| |
| verify(heldCall).unhold(); |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldHoldActiveHold() throws Exception { |
| BluetoothCall activeCall = createActiveCall(); |
| addCallCapability(activeCall, Connection.CAPABILITY_HOLD); |
| |
| boolean didProcess = mBluetoothInCallService.processChld( |
| CHLD_TYPE_HOLDACTIVE_ACCEPTHELD); |
| |
| verify(activeCall).hold(); |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldAddHeldToConfHolding() throws Exception { |
| BluetoothCall activeCall = createActiveCall(); |
| addCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE); |
| |
| boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_ADDHELDTOCONF); |
| |
| verify(activeCall).mergeConference(); |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldAddHeldToConf() throws Exception { |
| BluetoothCall activeCall = createActiveCall(); |
| removeCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE); |
| BluetoothCall conferenceableCall = getMockCall(); |
| ArrayList<String> conferenceableCalls = new ArrayList<>(); |
| conferenceableCalls.add(conferenceableCall.getTelecomCallId()); |
| mBluetoothInCallService.onCallAdded(conferenceableCall); |
| |
| when(activeCall.getConferenceableCalls()).thenReturn(conferenceableCalls); |
| |
| boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_ADDHELDTOCONF); |
| |
| verify(activeCall).conference(conferenceableCall); |
| Assert.assertTrue(didProcess); |
| } |
| |
| @Test |
| public void testProcessChldHoldActiveSwapConference() throws Exception { |
| // Create an active CDMA BluetoothCall with a BluetoothCall on hold |
| // and simulate a swapConference(). |
| BluetoothCall parentCall = createActiveCall(); |
| final BluetoothCall foregroundCall = getMockCall(); |
| final BluetoothCall heldCall = createHeldCall(); |
| addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE); |
| removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); |
| when(parentCall.isConference()).thenReturn(true); |
| when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false); |
| List<String> childrenIds = new LinkedList<String>(){{ |
| add(foregroundCall.getTelecomCallId()); |
| add(heldCall.getTelecomCallId()); |
| }}; |
| when(parentCall.getChildrenIds()).thenReturn(childrenIds); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| boolean didProcess = mBluetoothInCallService.processChld( |
| CHLD_TYPE_HOLDACTIVE_ACCEPTHELD); |
| |
| verify(parentCall).swapConference(); |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), eq(""), |
| eq(128), nullable(String.class)); |
| Assert.assertTrue(didProcess); |
| } |
| |
| // Testing the CallsManager Listener Functionality on Bluetooth |
| @Test |
| public void testOnCallAddedRinging() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000")); |
| |
| mBluetoothInCallService.onCallAdded(ringingCall); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), |
| eq("555000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class)); |
| } |
| |
| @Test |
| public void testSilentRingingCallState() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| when(ringingCall.isSilentRingingRequested()).thenReturn(true); |
| when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000")); |
| |
| mBluetoothInCallService.onCallAdded(ringingCall); |
| |
| verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), |
| anyString(), anyInt(), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallAddedCdmaActiveHold() throws Exception { |
| // BluetoothCall has been put into a CDMA "conference" with one BluetoothCall on hold. |
| BluetoothCall parentCall = createActiveCall(); |
| final BluetoothCall foregroundCall = getMockCall(); |
| final BluetoothCall heldCall = createHeldCall(); |
| addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE); |
| removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); |
| when(parentCall.isConference()).thenReturn(true); |
| List<String> childrenIds = new LinkedList<String>(){{ |
| add(foregroundCall.getTelecomCallId()); |
| add(heldCall.getTelecomCallId()); |
| }}; |
| when(parentCall.getChildrenIds()).thenReturn(childrenIds); |
| |
| mBluetoothInCallService.onCallAdded(parentCall); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallRemoved() throws Exception { |
| BluetoothCall activeCall = createActiveCall(); |
| mBluetoothInCallService.onCallAdded(activeCall); |
| doReturn(null).when(mMockCallInfo).getActiveCall(); |
| mBluetoothInCallService.onCallRemoved(activeCall); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChangedConnectingCall() throws Exception { |
| BluetoothCall activeCall = getMockCall(); |
| BluetoothCall connectingCall = getMockCall(); |
| when(connectingCall.getState()).thenReturn(Call.STATE_CONNECTING); |
| ArrayList<BluetoothCall> calls = new ArrayList<>(); |
| calls.add(connectingCall); |
| calls.add(activeCall); |
| mBluetoothInCallService.onCallAdded(connectingCall); |
| mBluetoothInCallService.onCallAdded(activeCall); |
| when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls); |
| |
| mBluetoothInCallService.getCallback(activeCall) |
| .onStateChanged(activeCall, Call.STATE_HOLDING); |
| |
| verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), |
| anyString(), anyInt(), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallAddedAudioProcessing() throws Exception { |
| BluetoothCall call = getMockCall(); |
| when(call.getState()).thenReturn(Call.STATE_AUDIO_PROCESSING); |
| mBluetoothInCallService.onCallAdded(call); |
| |
| verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), |
| anyString(), anyInt(), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChangedRingingToAudioProcessing() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000")); |
| |
| mBluetoothInCallService.onCallAdded(ringingCall); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), |
| eq("555000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class)); |
| |
| when(ringingCall.getState()).thenReturn(Call.STATE_AUDIO_PROCESSING); |
| when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(null); |
| |
| mBluetoothInCallService.getCallback(ringingCall) |
| .onStateChanged(ringingCall, Call.STATE_AUDIO_PROCESSING); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChangedAudioProcessingToSimulatedRinging() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); |
| mBluetoothInCallService.onCallAdded(ringingCall); |
| mBluetoothInCallService.getCallback(ringingCall) |
| .onStateChanged(ringingCall, Call.STATE_SIMULATED_RINGING); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), |
| eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChangedAudioProcessingToActive() throws Exception { |
| BluetoothCall activeCall = createActiveCall(); |
| when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE); |
| mBluetoothInCallService.onCallAdded(activeCall); |
| mBluetoothInCallService.getCallback(activeCall) |
| .onStateChanged(activeCall, Call.STATE_ACTIVE); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChangedDialing() throws Exception { |
| BluetoothCall activeCall = createActiveCall(); |
| |
| // make "mLastState" STATE_CONNECTING |
| BluetoothInCallService.CallStateCallback callback = |
| mBluetoothInCallService.new CallStateCallback(Call.STATE_CONNECTING); |
| mBluetoothInCallService.mCallbacks.put( |
| activeCall.getTelecomCallId(), callback); |
| |
| mBluetoothInCallService.mCallbacks.get(activeCall.getTelecomCallId()) |
| .onStateChanged(activeCall, Call.STATE_DIALING); |
| |
| verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), |
| anyString(), anyInt(), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChangedAlerting() throws Exception { |
| BluetoothCall outgoingCall = createOutgoingCall(); |
| mBluetoothInCallService.onCallAdded(outgoingCall); |
| mBluetoothInCallService.getCallback(outgoingCall) |
| .onStateChanged(outgoingCall, Call.STATE_DIALING); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DIALING), |
| eq(""), eq(128), nullable(String.class)); |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_ALERTING), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChangedDisconnected() throws Exception { |
| BluetoothCall disconnectedCall = createDisconnectedCall(); |
| doReturn(true).when(mMockCallInfo).hasOnlyDisconnectedCalls(); |
| mBluetoothInCallService.onCallAdded(disconnectedCall); |
| mBluetoothInCallService.getCallback(disconnectedCall) |
| .onStateChanged(disconnectedCall, Call.STATE_DISCONNECTED); |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChanged() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); |
| mBluetoothInCallService.onCallAdded(ringingCall); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), |
| eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class)); |
| |
| //Switch to active |
| doReturn(null).when(mMockCallInfo).getRingingOrSimulatedRingingCall(); |
| when(mMockCallInfo.getActiveCall()).thenReturn(ringingCall); |
| |
| mBluetoothInCallService.getCallback(ringingCall) |
| .onStateChanged(ringingCall, Call.STATE_ACTIVE); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnCallStateChangedGSMSwap() throws Exception { |
| BluetoothCall heldCall = createHeldCall(); |
| when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); |
| mBluetoothInCallService.onCallAdded(heldCall); |
| doReturn(2).when(mMockCallInfo).getNumHeldCalls(); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.getCallback(heldCall) |
| .onStateChanged(heldCall, Call.STATE_HOLDING); |
| |
| verify(mMockBluetoothHeadset, never()).phoneStateChanged(eq(0), eq(2), eq(CALL_STATE_HELD), |
| eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class)); |
| } |
| |
| @Test |
| public void testOnParentOnChildrenChanged() throws Exception { |
| // Start with two calls that are being merged into a CDMA conference call. The |
| // onIsConferencedChanged method will be called multiple times during the call. Make sure |
| // that the bluetooth phone state is updated properly. |
| BluetoothCall parentCall = createActiveCall(); |
| BluetoothCall activeCall = getMockCall(); |
| BluetoothCall heldCall = createHeldCall(); |
| mBluetoothInCallService.onCallAdded(parentCall); |
| mBluetoothInCallService.onCallAdded(activeCall); |
| mBluetoothInCallService.onCallAdded(heldCall); |
| String parentId = parentCall.getTelecomCallId(); |
| when(activeCall.getParentId()).thenReturn(parentId); |
| when(heldCall.getParentId()).thenReturn(parentId); |
| |
| ArrayList<String> calls = new ArrayList<>(); |
| calls.add(activeCall.getTelecomCallId()); |
| |
| when(parentCall.getChildrenIds()).thenReturn(calls); |
| when(parentCall.isConference()).thenReturn(true); |
| |
| removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); |
| addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE); |
| when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false); |
| |
| clearInvocations(mMockBluetoothHeadset); |
| // Be sure that onIsConferencedChanged rejects spurious changes during set up of |
| // CDMA "conference" |
| mBluetoothInCallService.getCallback(activeCall).onParentChanged(activeCall); |
| verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), |
| anyString(), anyInt(), nullable(String.class)); |
| |
| mBluetoothInCallService.getCallback(heldCall).onParentChanged(heldCall); |
| verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), |
| anyString(), anyInt(), nullable(String.class)); |
| |
| mBluetoothInCallService.getCallback(parentCall) |
| .onChildrenChanged( |
| parentCall, |
| mBluetoothInCallService.getBluetoothCallsByIds(calls)); |
| verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), |
| anyString(), anyInt(), nullable(String.class)); |
| |
| calls.add(heldCall.getTelecomCallId()); |
| mBluetoothInCallService.onCallAdded(heldCall); |
| mBluetoothInCallService.getCallback(parentCall) |
| .onChildrenChanged( |
| parentCall, |
| mBluetoothInCallService.getBluetoothCallsByIds(calls)); |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), |
| eq(""), eq(128), nullable(String.class)); |
| } |
| |
| @Test |
| public void testBluetoothAdapterReceiver() throws Exception { |
| BluetoothCall ringingCall = createRingingCall(); |
| when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:5550000")); |
| |
| Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); |
| intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON); |
| clearInvocations(mMockBluetoothHeadset); |
| mBluetoothInCallService.mBluetoothAdapterReceiver |
| = mBluetoothInCallService.new BluetoothAdapterReceiver(); |
| mBluetoothInCallService.mBluetoothAdapterReceiver |
| .onReceive(mBluetoothInCallService, intent); |
| |
| verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), |
| eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class)); |
| } |
| |
| private void addCallCapability(BluetoothCall call, int capability) { |
| when(call.can(capability)).thenReturn(true); |
| } |
| |
| private void removeCallCapability(BluetoothCall call, int capability) { |
| when(call.can(capability)).thenReturn(false); |
| } |
| |
| private BluetoothCall createActiveCall() { |
| BluetoothCall call = getMockCall(); |
| when(mMockCallInfo.getActiveCall()).thenReturn(call); |
| return call; |
| } |
| |
| private BluetoothCall createRingingCall() { |
| BluetoothCall call = getMockCall(); |
| Log.i("BluetoothInCallService", "asdf creaete " + Integer.toString(call.hashCode())); |
| when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(call); |
| return call; |
| } |
| |
| private BluetoothCall createHeldCall() { |
| BluetoothCall call = getMockCall(); |
| when(mMockCallInfo.getHeldCall()).thenReturn(call); |
| return call; |
| } |
| |
| private BluetoothCall createOutgoingCall() { |
| BluetoothCall call = getMockCall(); |
| when(mMockCallInfo.getOutgoingCall()).thenReturn(call); |
| return call; |
| } |
| |
| private BluetoothCall createDisconnectedCall() { |
| BluetoothCall call = getMockCall(); |
| when(mMockCallInfo.getCallByState(Call.STATE_DISCONNECTED)).thenReturn(call); |
| return call; |
| } |
| |
| private BluetoothCall createForegroundCall() { |
| BluetoothCall call = getMockCall(); |
| when(mMockCallInfo.getForegroundCall()).thenReturn(call); |
| return call; |
| } |
| |
| private static ComponentName makeQuickConnectionServiceComponentName() { |
| return new ComponentName("com.android.server.telecom.tests", |
| "com.android.server.telecom.tests.MockConnectionService"); |
| } |
| |
| private static PhoneAccountHandle makeQuickAccountHandle(String id) { |
| return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id, |
| Binder.getCallingUserHandle()); |
| } |
| |
| private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) { |
| return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx); |
| } |
| |
| private PhoneAccount makeQuickAccount(String id, int idx) { |
| return makeQuickAccountBuilder(id, idx) |
| .setAddress(Uri.parse(TEST_ACCOUNT_ADDRESS + idx)) |
| .setSubscriptionAddress(Uri.parse("tel:555-000" + idx)) |
| .setCapabilities(idx) |
| .setShortDescription("desc" + idx) |
| .setIsEnabled(true) |
| .build(); |
| } |
| |
| private BluetoothCall getMockCall() { |
| BluetoothCall call = mock(com.android.bluetooth.hfp.BluetoothCall.class); |
| String uuid = UUID.randomUUID().toString(); |
| when(call.getTelecomCallId()).thenReturn(uuid); |
| return call; |
| } |
| } |