blob: ea787aa7330fe64e7bbba9613452bc4bcc90f334 [file] [log] [blame]
/*
* 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.telephony;
import static com.android.bluetooth.telephony.BluetoothInCallService.CLCC_INFERENCE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothLeCallControl;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.DeviceConfig;
import android.telecom.BluetoothCallQualityReport;
import android.telecom.Call;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
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.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.hfp.BluetoothHeadsetProxy;
import com.android.bluetooth.tbs.BluetoothLeCallControlProxy;
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.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
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 BluetoothLeCallControlProxy mMockBluetoothLeCallControl;
@Mock
private BluetoothInCallService.CallInfo mMockCallInfo;
@Mock
private TelephonyManager mMockTelephonyManager;
@Mock
private Context mContext = ApplicationProvider.getApplicationContext();
public class TestableBluetoothInCallService extends BluetoothInCallService {
@Override
public IBinder onBind(Intent intent) {
IBinder binder = super.onBind(intent);
IntentFilter intentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(mBluetoothAdapterReceiver, intentFilter);
mTelephonyManager = getSystemService(TelephonyManager.class);
mTelecomManager = getSystemService(TelecomManager.class);
return binder;
}
@Override
protected void enforceModifyPermission() {
}
protected void setOnCreateCalled(boolean called) {
mOnCreateCalled = called;
}
}
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity();
// 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.setBluetoothLeCallControl(mMockBluetoothLeCallControl);
mBluetoothInCallService.mCallInfo = mMockCallInfo;
mBluetoothInCallService.setOnCreateCalled(true);
}
@After
public void tearDown() throws Exception {
mServiceRule.unbindService();
mBluetoothInCallService = null;
}
@Test
public void testHeadsetAnswerCall() throws Exception {
BluetoothCall mockCall = createRingingCall(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
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);
}
/**
* Verifies bluetooth call quality reports are properly parceled and set as a call event to
* Telecom.
*/
@Test
public void testBluetoothCallQualityReport() {
BluetoothCall activeCall = createForegroundCall(UUID.randomUUID());
when(activeCall.isCallNull()).thenReturn(false);
mBluetoothInCallService.onCallAdded(activeCall);
mBluetoothInCallService.sendBluetoothCallQualityReport(
10, // long timestamp
20, // int rssi
30, // int snr
40, // int retransmissionCount
50, // int packetsNotReceiveCount
60 // int negativeAcknowledgementCount
);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(activeCall).sendCallEvent(
eq(BluetoothCallQualityReport.EVENT_BLUETOOTH_CALL_QUALITY_REPORT),
bundleCaptor.capture());
Bundle bundle = bundleCaptor.getValue();
BluetoothCallQualityReport report = (BluetoothCallQualityReport) bundle.get(
BluetoothCallQualityReport.EXTRA_BLUETOOTH_CALL_QUALITY_REPORT);
Assert.assertEquals(10, report.getSentTimestampMillis());
Assert.assertEquals(20, report.getRssiDbm());
Assert.assertEquals(30, report.getSnrDb());
Assert.assertEquals(40, report.getRetransmittedPacketsCount());
Assert.assertEquals(50, report.getPacketsNotReceivedCount());
Assert.assertEquals(60, report.getNegativeAcknowledgementCount());
}
@Test
public void testListCurrentCallsSilentRinging() throws Exception {
ArrayList<BluetoothCall> calls = new ArrayList<>();
BluetoothCall silentRingingCall = createActiveCall(UUID.randomUUID());
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(UUID.randomUUID());
final BluetoothCall confCall1 = getMockCall(UUID.randomUUID());
final BluetoothCall confCall2 = createHeldCall(UUID.randomUUID());
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);
Integer confCall1Id = confCall1.getId();
when(parentCall.getGenericConferenceActiveChildCallId())
.thenReturn(confCall1Id);
when(parentCall.isConference()).thenReturn(true);
List<Integer> childrenIds = Arrays.asList(confCall1.getId(),
confCall2.getId());
when(parentCall.getChildrenIds()).thenReturn(childrenIds);
//Add links from child calls to parent
Integer parentId = parentCall.getId();
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(UUID.randomUUID());
when(parentCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
final BluetoothCall foregroundCall = getMockCall(UUID.randomUUID());
when(foregroundCall.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
final BluetoothCall heldCall = createHeldCall(UUID.randomUUID());
when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0002"));
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-0001")));
when(heldCall.getGatewayInfo()).thenReturn(
new GatewayInfo(null, null, Uri.parse("tel:555-0002")));
addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
Integer foregroundCallId = foregroundCall.getId();
when(parentCall.getGenericConferenceActiveChildCallId()).thenReturn(foregroundCallId);
when(parentCall.isConference()).thenReturn(true);
List<Integer> childrenIds = Arrays.asList(foregroundCall.getId(),
heldCall.getId());
when(parentCall.getChildrenIds()).thenReturn(childrenIds);
//Add links from child calls to parent
Integer parentId = parentCall.getId();
when(foregroundCall.getParentId()).thenReturn(parentId);
when(heldCall.getParentId()).thenReturn(parentId);
when(parentCall.hasProperty(Call.Details.PROPERTY_GENERIC_CONFERENCE)).thenReturn(true);
clearInvocations(mMockBluetoothHeadset);
mBluetoothInCallService.listCurrentCalls();
verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0),
eq(false), eq("5550001"), eq(PhoneNumberUtils.TOA_Unknown));
verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_HELD), eq(0),
eq(false), eq("5550002"), 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(UUID.randomUUID());
final BluetoothCall confCall1 = getMockCall(UUID.randomUUID());
final BluetoothCall confCall2 = createHeldCall(UUID.randomUUID());
when(parentCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
when(confCall1.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
when(confCall2.getHandle()).thenReturn(Uri.parse("tel:555-0002"));
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<Integer> childrenIds = Arrays.asList(confCall1.getId(),
confCall2.getId());
when(parentCall.getChildrenIds()).thenReturn(childrenIds);
//Add links from child calls to parent
Integer parentId = parentCall.getId();
when(confCall1.getParentId()).thenReturn(parentId);
when(confCall2.getParentId()).thenReturn(parentId);
when(parentCall.hasProperty(Call.Details.PROPERTY_GENERIC_CONFERENCE)).thenReturn(true);
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(UUID.randomUUID());
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);
when(waitingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
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(UUID.randomUUID());
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(UUID.randomUUID());
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.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
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(UUID.randomUUID());
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.getHandle()).thenReturn(Uri.parse("tel:5550000"));
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(UUID.randomUUID());
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.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
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(UUID.randomUUID());
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.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
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(UUID.randomUUID());
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.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
when(dialingCall.getGatewayInfo()).thenReturn(
new GatewayInfo(null, null, Uri.parse("tel:555-0000")));
BluetoothCall holdingCall = createHeldCall(UUID.randomUUID());
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.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
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(UUID.randomUUID());
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(parentCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
calls.add(parentCall);
mBluetoothInCallService.onCallAdded(parentCall);
clearInvocations(mMockBluetoothHeadset);
mBluetoothInCallService.listCurrentCalls();
verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(1), eq(CALL_STATE_ACTIVE), eq(0),
eq(true), eq("5550000"), eq(129));
verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
}
@Test
public void testListCurrentCallsHeldImsCepConference() throws Exception {
ArrayList<BluetoothCall> calls = new ArrayList<>();
BluetoothCall parentCall = createHeldCall(UUID.randomUUID());
BluetoothCall childCall1 = createActiveCall(UUID.randomUUID());
BluetoothCall childCall2 = createActiveCall(UUID.randomUUID());
when(parentCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
when(childCall1.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
when(childCall2.getHandle()).thenReturn(Uri.parse("tel:555-0002"));
calls.add(parentCall);
calls.add(childCall1);
calls.add(childCall2);
mBluetoothInCallService.onCallAdded(parentCall);
mBluetoothInCallService.onCallAdded(childCall1);
mBluetoothInCallService.onCallAdded(childCall2);
addCallCapability(parentCall, Connection.CAPABILITY_MANAGE_CONFERENCE);
Integer parentId = parentCall.getId();
when(childCall1.getParentId()).thenReturn(parentId);
when(childCall2.getParentId()).thenReturn(parentId);
List<Integer> childrenIds = Arrays.asList(childCall1.getId(),
childCall2.getId());
when(parentCall.getChildrenIds()).thenReturn(childrenIds);
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.hasProperty(Call.Details.PROPERTY_GENERIC_CONFERENCE)).thenReturn(true);
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), eq("5550001"), eq(PhoneNumberUtils.TOA_Unknown));
verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(0), eq(CALL_STATE_HELD), eq(0),
eq(true), eq("5550002"), eq(PhoneNumberUtils.TOA_Unknown));
verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
}
@Test
public void testListCurrentCallsConferenceGetChildrenIsEmpty() throws Exception {
ArrayList<BluetoothCall> calls = new ArrayList<>();
BluetoothCall conferenceCall = createActiveCall(UUID.randomUUID());
when(conferenceCall.getHandle()).thenReturn(Uri.parse("tel:555-1234"));
addCallCapability(conferenceCall, Connection.CAPABILITY_MANAGE_CONFERENCE);
when(conferenceCall.isConference()).thenReturn(true);
when(conferenceCall.getState()).thenReturn(Call.STATE_ACTIVE);
when(conferenceCall.hasProperty(Call.Details.PROPERTY_GENERIC_CONFERENCE)).thenReturn(true);
when(conferenceCall.can(Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN))
.thenReturn(false);
when(conferenceCall.isIncoming()).thenReturn(true);
when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
calls.add(conferenceCall);
mBluetoothInCallService.onCallAdded(conferenceCall);
clearInvocations(mMockBluetoothHeadset);
mBluetoothInCallService.listCurrentCalls();
verify(mMockBluetoothHeadset).clccResponse(
eq(1), eq(1), eq(0), eq(0), eq(true), eq("5551234"), eq(129));
}
@Test
public void testListCurrentCallsConferenceEmptyChildrenInference() throws Exception {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH, CLCC_INFERENCE, "true", false);
ArrayList<BluetoothCall> calls = new ArrayList<>();
when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
// active call is added
BluetoothCall activeCall = createActiveCall(UUID.randomUUID());
calls.add(activeCall);
mBluetoothInCallService.onCallAdded(activeCall);
when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE);
when(activeCall.isIncoming()).thenReturn(false);
when(activeCall.isConference()).thenReturn(false);
when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
when(activeCall.getGatewayInfo())
.thenReturn(new GatewayInfo(null, null, Uri.parse("tel:555-0001")));
// holding call is added
BluetoothCall holdingCall = createHeldCall(UUID.randomUUID());
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.getHandle()).thenReturn(Uri.parse("tel:555-0002"));
when(holdingCall.getGatewayInfo())
.thenReturn(new GatewayInfo(null, null, Uri.parse("tel:555-0002")));
// needs to have at least one CLCC response before merge to enable call inference
clearInvocations(mMockBluetoothHeadset);
mBluetoothInCallService.listCurrentCalls();
verify(mMockBluetoothHeadset)
.clccResponse(
1, 0, CALL_STATE_ACTIVE, 0, false, "5550001", PhoneNumberUtils.TOA_Unknown);
verify(mMockBluetoothHeadset)
.clccResponse(
2, 1, CALL_STATE_HELD, 0, false, "5550002", PhoneNumberUtils.TOA_Unknown);
calls.clear();
// calls merged for conference call
DisconnectCause cause = new DisconnectCause(DisconnectCause.OTHER);
when(activeCall.getDisconnectCause()).thenReturn(cause);
when(holdingCall.getDisconnectCause()).thenReturn(cause);
mBluetoothInCallService.onCallRemoved(activeCall, true);
mBluetoothInCallService.onCallRemoved(holdingCall, true);
BluetoothCall conferenceCall = createActiveCall(UUID.randomUUID());
addCallCapability(conferenceCall, Connection.CAPABILITY_MANAGE_CONFERENCE);
when(conferenceCall.getHandle()).thenReturn(Uri.parse("tel:555-1234"));
when(conferenceCall.isConference()).thenReturn(true);
when(conferenceCall.getState()).thenReturn(Call.STATE_ACTIVE);
when(conferenceCall.hasProperty(Call.Details.PROPERTY_GENERIC_CONFERENCE)).thenReturn(true);
when(conferenceCall.can(Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN))
.thenReturn(false);
when(conferenceCall.isIncoming()).thenReturn(true);
when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
// parent call arrived, but children have not, then do inference on children
calls.add(conferenceCall);
Assert.assertEquals(calls.size(), 1);
mBluetoothInCallService.onCallAdded(conferenceCall);
clearInvocations(mMockBluetoothHeadset);
mBluetoothInCallService.listCurrentCalls();
verify(mMockBluetoothHeadset)
.clccResponse(
1, 0, CALL_STATE_ACTIVE, 0, true, "5550001", PhoneNumberUtils.TOA_Unknown);
verify(mMockBluetoothHeadset)
.clccResponse(
2, 1, CALL_STATE_ACTIVE, 0, true, "5550002", PhoneNumberUtils.TOA_Unknown);
// real children arrive, no change on CLCC response
calls.add(activeCall);
mBluetoothInCallService.onCallAdded(activeCall);
when(activeCall.isConference()).thenReturn(true);
calls.add(holdingCall);
mBluetoothInCallService.onCallAdded(holdingCall);
when(holdingCall.getState()).thenReturn(Call.STATE_ACTIVE);
when(holdingCall.isConference()).thenReturn(true);
when(conferenceCall.getChildrenIds()).thenReturn(new ArrayList<>(Arrays.asList(1, 2)));
clearInvocations(mMockBluetoothHeadset);
mBluetoothInCallService.listCurrentCalls();
verify(mMockBluetoothHeadset)
.clccResponse(
1, 0, CALL_STATE_ACTIVE, 0, true, "5550001", PhoneNumberUtils.TOA_Unknown);
verify(mMockBluetoothHeadset)
.clccResponse(
2, 1, CALL_STATE_ACTIVE, 0, true, "5550002", PhoneNumberUtils.TOA_Unknown);
// when call is terminated, children first removed, then parent
cause = new DisconnectCause(DisconnectCause.LOCAL);
when(activeCall.getDisconnectCause()).thenReturn(cause);
when(holdingCall.getDisconnectCause()).thenReturn(cause);
mBluetoothInCallService.onCallRemoved(activeCall, true);
mBluetoothInCallService.onCallRemoved(holdingCall, true);
calls.remove(activeCall);
calls.remove(holdingCall);
Assert.assertEquals(calls.size(), 1);
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());
// when parent is removed
when(conferenceCall.getDisconnectCause()).thenReturn(cause);
calls.remove(conferenceCall);
mBluetoothInCallService.onCallRemoved(conferenceCall, true);
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());
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH, CLCC_INFERENCE, "false", false);
}
@Test
public void testQueryPhoneState() throws Exception {
BluetoothCall ringingCall = createRingingCall(UUID.randomUUID());
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(UUID.randomUUID());
final BluetoothCall confCall1 = getMockCall(UUID.randomUUID());
final BluetoothCall confCall2 = getMockCall(UUID.randomUUID());
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<Integer> childrenIds = Arrays.asList(confCall1.getId(),
confCall2.getId());
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(UUID.randomUUID());
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(UUID.randomUUID());
boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_RELEASEHELD);
verify(onHoldCall).disconnect();
Assert.assertTrue(didProcess);
}
@Test
public void testProcessChldReleaseActiveRinging() throws Exception {
BluetoothCall activeCall = createActiveCall(UUID.randomUUID());
BluetoothCall ringingCall = createRingingCall(UUID.randomUUID());
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(UUID.randomUUID());
BluetoothCall heldCall = createHeldCall(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
boolean didProcess = mBluetoothInCallService.processChld(
CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
verify(heldCall).unhold();
Assert.assertTrue(didProcess);
}
@Test
public void testProcessChldHoldActiveHold() throws Exception {
BluetoothCall activeCall = createActiveCall(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
removeCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE);
BluetoothCall conferenceableCall = getMockCall(UUID.randomUUID());
ArrayList<Integer> conferenceableCalls = new ArrayList<>();
conferenceableCalls.add(conferenceableCall.getId());
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(UUID.randomUUID());
final BluetoothCall foregroundCall = getMockCall(UUID.randomUUID());
when(foregroundCall.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
final BluetoothCall heldCall = createHeldCall(UUID.randomUUID());
when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0002"));
addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
when(parentCall.isConference()).thenReturn(true);
when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false);
when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
List<Integer> childrenIds = Arrays.asList(foregroundCall.getId(),
heldCall.getId());
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(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
final BluetoothCall foregroundCall = getMockCall(UUID.randomUUID());
final BluetoothCall heldCall = createHeldCall(UUID.randomUUID());
when(foregroundCall.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0002"));
addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
when(parentCall.isConference()).thenReturn(true);
List<Integer> childrenIds = Arrays.asList(foregroundCall.getId(),
heldCall.getId());
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(UUID.randomUUID());
mBluetoothInCallService.onCallAdded(activeCall);
doReturn(null).when(mMockCallInfo).getActiveCall();
when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
mBluetoothInCallService.onCallRemoved(activeCall, true /* forceRemoveCallback */);
verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
eq(""), eq(128), nullable(String.class));
}
@Test
public void testOnDetailsChangeExternalRemovesCall() throws Exception {
BluetoothCall activeCall = createActiveCall(UUID.randomUUID());
mBluetoothInCallService.onCallAdded(activeCall);
doReturn(null).when(mMockCallInfo).getActiveCall();
when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
when(activeCall.isExternalCall()).thenReturn(true);
mBluetoothInCallService.getCallback(activeCall).onDetailsChanged(activeCall, null);
verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
eq(""), eq(128), nullable(String.class));
}
@Test
public void testOnDetailsChangeExternalAddsCall() throws Exception {
BluetoothCall activeCall = createActiveCall(UUID.randomUUID());
mBluetoothInCallService.onCallAdded(activeCall);
when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-0001"));
BluetoothInCallService.CallStateCallback callBack = mBluetoothInCallService.getCallback(
activeCall);
when(activeCall.isExternalCall()).thenReturn(true);
callBack.onDetailsChanged(activeCall, null);
when(activeCall.isExternalCall()).thenReturn(false);
callBack.onDetailsChanged(activeCall, null);
verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
eq(""), eq(128), nullable(String.class));
}
@Test
public void testOnCallStateChangedConnectingCall() throws Exception {
BluetoothCall activeCall = getMockCall(UUID.randomUUID());
BluetoothCall connectingCall = getMockCall(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
// make "mLastState" STATE_CONNECTING
BluetoothInCallService.CallStateCallback callback =
mBluetoothInCallService.new CallStateCallback(Call.STATE_CONNECTING);
mBluetoothInCallService.mCallbacks.put(
activeCall.getId(), callback);
mBluetoothInCallService.mCallbacks.get(activeCall.getId())
.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(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
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(UUID.randomUUID());
BluetoothCall activeCall = getMockCall(UUID.randomUUID());
BluetoothCall heldCall = createHeldCall(UUID.randomUUID());
mBluetoothInCallService.onCallAdded(parentCall);
mBluetoothInCallService.onCallAdded(activeCall);
mBluetoothInCallService.onCallAdded(heldCall);
Integer parentId = parentCall.getId();
when(activeCall.getParentId()).thenReturn(parentId);
when(heldCall.getParentId()).thenReturn(parentId);
ArrayList<Integer> calls = new ArrayList<>();
calls.add(activeCall.getId());
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.getId());
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(UUID.randomUUID());
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));
}
@Test
public void testClear() {
doNothing().when(mContext).unregisterReceiver(any(
BluetoothInCallService.BluetoothAdapterReceiver.class));
mBluetoothInCallService.attachBaseContext(mContext);
mBluetoothInCallService.mBluetoothAdapterReceiver
= mBluetoothInCallService.new BluetoothAdapterReceiver();
Assert.assertNotNull(mBluetoothInCallService.mBluetoothAdapterReceiver);
Assert.assertNotNull(mBluetoothInCallService.mBluetoothHeadset);
mBluetoothInCallService.clear();
Assert.assertNull(mBluetoothInCallService.mBluetoothAdapterReceiver);
Assert.assertNull(mBluetoothInCallService.mBluetoothHeadset);
}
@Test
public void testGetBearerTechnology() {
mBluetoothInCallService.mTelephonyManager = mMockTelephonyManager;
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_GSM);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_GSM);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_GPRS);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_2G);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_EVDO_B);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_3G);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_TD_SCDMA);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_WCDMA);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_LTE);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_LTE);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_1xRTT);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_CDMA);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_HSPAP);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_4G);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_IWLAN);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_WIFI);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_NR);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_5G);
when(mMockTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_LTE_CA);
Assert.assertEquals(mBluetoothInCallService.getBearerTechnology(),
BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_GSM);
}
@Test
public void testGetTbsTerminationReason() {
BluetoothCall call = getMockCall(UUID.randomUUID());
when(call.getDisconnectCause()).thenReturn(null);
Assert.assertEquals(mBluetoothInCallService.getTbsTerminationReason(call),
BluetoothLeCallControl.TERMINATION_REASON_FAIL);
DisconnectCause cause = new DisconnectCause(DisconnectCause.BUSY, null, null, null, 1);
when(call.getDisconnectCause()).thenReturn(cause);
Assert.assertEquals(mBluetoothInCallService.getTbsTerminationReason(call),
BluetoothLeCallControl.TERMINATION_REASON_LINE_BUSY);
cause = new DisconnectCause(DisconnectCause.REJECTED, null, null, null, 1);
when(call.getDisconnectCause()).thenReturn(cause);
Assert.assertEquals(mBluetoothInCallService.getTbsTerminationReason(call),
BluetoothLeCallControl.TERMINATION_REASON_REMOTE_HANGUP);
cause = new DisconnectCause(DisconnectCause.LOCAL, null, null, null, 1);
when(call.getDisconnectCause()).thenReturn(cause);
mBluetoothInCallService.mIsTerminatedByClient = false;
Assert.assertEquals(mBluetoothInCallService.getTbsTerminationReason(call),
BluetoothLeCallControl.TERMINATION_REASON_SERVER_HANGUP);
cause = new DisconnectCause(DisconnectCause.LOCAL, null, null, null, 1);
when(call.getDisconnectCause()).thenReturn(cause);
mBluetoothInCallService.mIsTerminatedByClient = true;
Assert.assertEquals(mBluetoothInCallService.getTbsTerminationReason(call),
BluetoothLeCallControl.TERMINATION_REASON_CLIENT_HANGUP);
cause = new DisconnectCause(DisconnectCause.ERROR, null, null, null, 1);
when(call.getDisconnectCause()).thenReturn(cause);
Assert.assertEquals(mBluetoothInCallService.getTbsTerminationReason(call),
BluetoothLeCallControl.TERMINATION_REASON_NETWORK_CONGESTION);
cause = new DisconnectCause(
DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED, null, null, null, 1);
when(call.getDisconnectCause()).thenReturn(cause);
Assert.assertEquals(mBluetoothInCallService.getTbsTerminationReason(call),
BluetoothLeCallControl.TERMINATION_REASON_INVALID_URI);
cause = new DisconnectCause(DisconnectCause.ERROR, null, null, null, 1);
when(call.getDisconnectCause()).thenReturn(cause);
Assert.assertEquals(mBluetoothInCallService.getTbsTerminationReason(call),
BluetoothLeCallControl.TERMINATION_REASON_NETWORK_CONGESTION);
}
@Test
public void testOnCreate() {
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = Build.VERSION_CODES.S;
when(mContext.getApplicationInfo()).thenReturn(applicationInfo);
mBluetoothInCallService.attachBaseContext(mContext);
mBluetoothInCallService.setOnCreateCalled(false);
Assert.assertNull(mBluetoothInCallService.mBluetoothAdapterReceiver);
mBluetoothInCallService.onCreate();
Assert.assertNotNull(mBluetoothInCallService.mBluetoothAdapterReceiver);
Assert.assertTrue(mBluetoothInCallService.mOnCreateCalled);
}
@Test
public void testOnDestroy() {
Assert.assertTrue(mBluetoothInCallService.mOnCreateCalled);
mBluetoothInCallService.onDestroy();
Assert.assertFalse(mBluetoothInCallService.mOnCreateCalled);
}
@Test
public void testLeCallControlCallback_onAcceptCall_withUnknownCallId() {
BluetoothLeCallControlProxy callControlProxy = mock(BluetoothLeCallControlProxy.class);
mBluetoothInCallService.mBluetoothLeCallControl = callControlProxy;
BluetoothLeCallControl.Callback callback =
mBluetoothInCallService.mBluetoothLeCallControlCallback;
int requestId = 1;
UUID unknownCallId = UUID.randomUUID();
callback.onAcceptCall(requestId, unknownCallId);
verify(callControlProxy).requestResult(
requestId, BluetoothLeCallControl.RESULT_ERROR_UNKNOWN_CALL_ID);
}
@Test
public void testLeCallControlCallback_onTerminateCall_withUnknownCallId() {
BluetoothLeCallControlProxy callControlProxy = mock(BluetoothLeCallControlProxy.class);
mBluetoothInCallService.mBluetoothLeCallControl = callControlProxy;
BluetoothLeCallControl.Callback callback =
mBluetoothInCallService.mBluetoothLeCallControlCallback;
int requestId = 1;
UUID unknownCallId = UUID.randomUUID();
callback.onTerminateCall(requestId, unknownCallId);
verify(callControlProxy).requestResult(
requestId, BluetoothLeCallControl.RESULT_ERROR_UNKNOWN_CALL_ID);
}
@Test
public void testLeCallControlCallback_onHoldCall_withUnknownCallId() {
BluetoothLeCallControlProxy callControlProxy = mock(BluetoothLeCallControlProxy.class);
mBluetoothInCallService.mBluetoothLeCallControl = callControlProxy;
BluetoothLeCallControl.Callback callback =
mBluetoothInCallService.mBluetoothLeCallControlCallback;
int requestId = 1;
UUID unknownCallId = UUID.randomUUID();
callback.onHoldCall(requestId, unknownCallId);
verify(callControlProxy).requestResult(
requestId, BluetoothLeCallControl.RESULT_ERROR_UNKNOWN_CALL_ID);
}
@Test
public void testLeCallControlCallback_onUnholdCall_withUnknownCallId() {
BluetoothLeCallControlProxy callControlProxy = mock(BluetoothLeCallControlProxy.class);
mBluetoothInCallService.mBluetoothLeCallControl = callControlProxy;
BluetoothLeCallControl.Callback callback =
mBluetoothInCallService.mBluetoothLeCallControlCallback;
int requestId = 1;
UUID unknownCallId = UUID.randomUUID();
callback.onUnholdCall(requestId, unknownCallId);
verify(callControlProxy).requestResult(
requestId, BluetoothLeCallControl.RESULT_ERROR_UNKNOWN_CALL_ID);
}
@Test
public void testLeCallControlCallback_onJoinCalls() {
BluetoothLeCallControlProxy callControlProxy = mock(BluetoothLeCallControlProxy.class);
mBluetoothInCallService.mBluetoothLeCallControl = callControlProxy;
BluetoothLeCallControl.Callback callback =
mBluetoothInCallService.mBluetoothLeCallControlCallback;
int requestId = 1;
UUID baseCallId = UUID.randomUUID();
UUID firstJoiningCallId = UUID.randomUUID();
UUID secondJoiningCallId = UUID.randomUUID();
List<UUID> uuids = new ArrayList<>(Arrays.asList(baseCallId, firstJoiningCallId,
secondJoiningCallId));
ArrayList<BluetoothCall> calls = new ArrayList<>();
BluetoothCall baseCall = createActiveCall(baseCallId);
BluetoothCall firstCall = createRingingCall(firstJoiningCallId);
BluetoothCall secondCall = createRingingCall(secondJoiningCallId);
when(baseCall.getState()).thenReturn(Call.STATE_ACTIVE);
when(firstCall.getState()).thenReturn(Call.STATE_RINGING);
when(secondCall.getState()).thenReturn(Call.STATE_RINGING);
calls.add(baseCall);
calls.add(firstCall);
calls.add(secondCall);
mBluetoothInCallService.onCallAdded(baseCall);
mBluetoothInCallService.onCallAdded(firstCall);
mBluetoothInCallService.onCallAdded(secondCall);
when(baseCall.getHandle()).thenReturn(Uri.parse("tel:111-111"));
when(firstCall.getHandle()).thenReturn(Uri.parse("tel:222-222"));
when(secondCall.getHandle()).thenReturn(Uri.parse("tel:333-333"));
when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
doReturn(baseCall).when(mMockCallInfo).getCallByCallId(baseCallId);
doReturn(firstCall).when(mMockCallInfo).getCallByCallId(firstJoiningCallId);
doReturn(secondCall).when(mMockCallInfo).getCallByCallId(secondJoiningCallId);
callback.onJoinCalls(requestId, uuids);
verify(callControlProxy).requestResult(
requestId, BluetoothLeCallControl.RESULT_SUCCESS);
verify(baseCall, times(2)).conference(any(BluetoothCall.class));
}
@Test
public void testLeCallControlCallback_onJoinCalls_omitDoubledCalls() {
BluetoothLeCallControlProxy callControlProxy = mock(BluetoothLeCallControlProxy.class);
mBluetoothInCallService.mBluetoothLeCallControl = callControlProxy;
BluetoothLeCallControl.Callback callback =
mBluetoothInCallService.mBluetoothLeCallControlCallback;
int requestId = 1;
UUID baseCallId = UUID.randomUUID();
UUID firstJoiningCallId = UUID.randomUUID();
List<UUID> uuids = new ArrayList<>(Arrays.asList(baseCallId, firstJoiningCallId,
firstJoiningCallId));
ArrayList<BluetoothCall> calls = new ArrayList<>();
BluetoothCall baseCall = createActiveCall(baseCallId);
BluetoothCall firstCall = createRingingCall(firstJoiningCallId);
when(baseCall.getState()).thenReturn(Call.STATE_ACTIVE);
when(firstCall.getState()).thenReturn(Call.STATE_RINGING);
calls.add(baseCall);
calls.add(firstCall);
mBluetoothInCallService.onCallAdded(baseCall);
mBluetoothInCallService.onCallAdded(firstCall);
when(baseCall.getHandle()).thenReturn(Uri.parse("tel:111-111"));
when(firstCall.getHandle()).thenReturn(Uri.parse("tel:222-222"));
when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
doReturn(baseCall).when(mMockCallInfo).getCallByCallId(baseCallId);
doReturn(firstCall).when(mMockCallInfo).getCallByCallId(firstJoiningCallId);
callback.onJoinCalls(requestId, uuids);
verify(callControlProxy).requestResult(
requestId, BluetoothLeCallControl.RESULT_SUCCESS);
verify(baseCall, times(1)).conference(any(BluetoothCall.class));
}
@Test
public void testLeCallControlCallback_onJoinCalls_omitNullCalls() {
BluetoothLeCallControlProxy callControlProxy = mock(BluetoothLeCallControlProxy.class);
mBluetoothInCallService.mBluetoothLeCallControl = callControlProxy;
BluetoothLeCallControl.Callback callback =
mBluetoothInCallService.mBluetoothLeCallControlCallback;
int requestId = 1;
UUID baseCallId = UUID.randomUUID();
UUID firstJoiningCallId = UUID.randomUUID();
UUID secondJoiningCallId = UUID.randomUUID();
List<UUID> uuids = new ArrayList<>(Arrays.asList(baseCallId, firstJoiningCallId,
secondJoiningCallId));
ArrayList<BluetoothCall> calls = new ArrayList<>();
BluetoothCall baseCall = createActiveCall(baseCallId);
BluetoothCall firstCall = createRingingCall(firstJoiningCallId);
BluetoothCall secondCall = createRingingCall(secondJoiningCallId);
when(baseCall.getState()).thenReturn(Call.STATE_ACTIVE);
when(firstCall.getState()).thenReturn(Call.STATE_RINGING);
when(secondCall.getState()).thenReturn(Call.STATE_RINGING);
calls.add(baseCall);
calls.add(firstCall);
calls.add(secondCall);
mBluetoothInCallService.onCallAdded(baseCall);
mBluetoothInCallService.onCallAdded(firstCall);
mBluetoothInCallService.onCallAdded(secondCall);
when(baseCall.getHandle()).thenReturn(Uri.parse("tel:111-111"));
when(firstCall.getHandle()).thenReturn(Uri.parse("tel:222-222"));
when(secondCall.getHandle()).thenReturn(Uri.parse("tel:333-333"));
when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
doReturn(baseCall).when(mMockCallInfo).getCallByCallId(null);
doReturn(firstCall).when(mMockCallInfo).getCallByCallId(firstJoiningCallId);
doReturn(secondCall).when(mMockCallInfo).getCallByCallId(secondJoiningCallId);
callback.onJoinCalls(requestId, uuids);
verify(callControlProxy).requestResult(
requestId, BluetoothLeCallControl.RESULT_SUCCESS);
verify(firstCall, times(1)).conference(any(BluetoothCall.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(UUID uuid) {
BluetoothCall call = getMockCall(uuid);
when(mMockCallInfo.getActiveCall()).thenReturn(call);
return call;
}
private BluetoothCall createRingingCall(UUID uuid) {
BluetoothCall call = getMockCall(uuid);
Log.i("BluetoothInCallService", "asdf creaete " + Integer.toString(call.hashCode()));
when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(call);
return call;
}
private BluetoothCall createHeldCall(UUID uuid) {
BluetoothCall call = getMockCall(uuid);
when(mMockCallInfo.getHeldCall()).thenReturn(call);
return call;
}
private BluetoothCall createOutgoingCall(UUID uuid) {
BluetoothCall call = getMockCall(uuid);
when(mMockCallInfo.getOutgoingCall()).thenReturn(call);
return call;
}
private BluetoothCall createDisconnectedCall(UUID uuid) {
BluetoothCall call = getMockCall(uuid);
when(mMockCallInfo.getCallByState(Call.STATE_DISCONNECTED)).thenReturn(call);
return call;
}
private BluetoothCall createForegroundCall(UUID uuid) {
BluetoothCall call = getMockCall(uuid);
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(UUID uuid) {
BluetoothCall call = mock(com.android.bluetooth.telephony.BluetoothCall.class);
Integer integerUuid = uuid.hashCode();
when(call.getId()).thenReturn(integerUuid);
return call;
}
}