Implement multi-hfp APIs
Plumb Telecom multi-hfp APIs all the way through the stack.
Also delete BluetoothManager (deprecated) and modify tests to fully test
the multi-hfp functionality
Bug: 64767509
Test: unit tests
Change-Id: I02aafe3fca759510a013fd7cd956e3e923dd408a
diff --git a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
index e70a63a..4d86f05 100644
--- a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
+++ b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
@@ -328,7 +328,7 @@
.getCallAudioRouteStateMachine().getHandler(),
TEST_TIMEOUT);
audioRoutes.add(mInCallServiceFixtureX.mCallAudioState.getRoute());
- mInCallServiceFixtureX.getInCallAdapter().setAudioRoute(CallAudioState.ROUTE_SPEAKER);
+ mInCallServiceFixtureX.getInCallAdapter().setAudioRoute(CallAudioState.ROUTE_SPEAKER, null);
waitForHandlerAction(
mTelecomSystem.getCallsManager().getCallAudioManager()
.getCallAudioRouteStateMachine().getHandler(),
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 905a15e..2a8dd51 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -555,10 +555,10 @@
verify(mAudioService, timeout(TEST_TIMEOUT))
.setMicrophoneMute(eq(false), any(String.class), any(Integer.class));
- mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
+ mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null);
verify(audioManager, timeout(TEST_TIMEOUT))
.setSpeakerphoneOn(true);
- mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE);
+ mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE, null);
verify(audioManager, timeout(TEST_TIMEOUT))
.setSpeakerphoneOn(false);
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothManagerTest.java
deleted file mode 100644
index d9a9e14..0000000
--- a/tests/src/com/android/server/telecom/tests/BluetoothManagerTest.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2016 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.server.telecom.tests;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
-import android.content.BroadcastReceiver;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.server.telecom.BluetoothAdapterProxy;
-import com.android.server.telecom.BluetoothHeadsetProxy;
-import com.android.server.telecom.BluetoothManager;
-
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-
-import java.util.Collections;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class BluetoothManagerTest extends TelecomTestCase {
- @Mock BluetoothManager.BluetoothStateListener mListener;
- @Mock BluetoothHeadsetProxy mHeadsetProxy;
- @Mock BluetoothAdapterProxy mAdapterProxy;
-
- BluetoothManager mBluetoothManager;
- BluetoothProfile.ServiceListener serviceListenerUnderTest;
- BroadcastReceiver receiverUnderTest;
-
- private BluetoothDevice device1;
-
- public void setUp() throws Exception {
- super.setUp();
- initializeDevice();
- mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
- mBluetoothManager = new BluetoothManager(mContext, mAdapterProxy);
-
- ArgumentCaptor<BluetoothProfile.ServiceListener> serviceCaptor =
- ArgumentCaptor.forClass(BluetoothProfile.ServiceListener.class);
- verify(mAdapterProxy).getProfileProxy(eq(mContext),
- serviceCaptor.capture(), eq(BluetoothProfile.HEADSET));
- serviceListenerUnderTest = serviceCaptor.getValue();
-
- ArgumentCaptor<BroadcastReceiver> receiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext).registerReceiver(receiverCaptor.capture(), any(IntentFilter.class));
- receiverUnderTest = receiverCaptor.getValue();
-
- mBluetoothManager.setBluetoothStateListener(mListener);
- mBluetoothManager.setBluetoothHeadsetForTesting(mHeadsetProxy);
- }
-
- @SmallTest
- public void testIsBluetoothAvailableWithNoDevices() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.<BluetoothDevice>emptyList());
- assertFalse(mBluetoothManager.isBluetoothAvailable());
- }
-
- @SmallTest
- public void testIsBluetoothAvailable() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- assertTrue(mBluetoothManager.isBluetoothAvailable());
- }
-
- @SmallTest
- public void testIsAudioConnectedWithNoDevices() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.<BluetoothDevice>emptyList());
- assertFalse(mBluetoothManager.isBluetoothAudioConnected());
- }
-
- @SmallTest
- public void testIsAudioConnectedWhenAudioNotOn() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(false);
- assertFalse(mBluetoothManager.isBluetoothAudioConnected());
- }
-
- @SmallTest
- public void testIsAudioConnectedWhenAudioOn() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(true);
- assertTrue(mBluetoothManager.isBluetoothAudioConnected());
- }
-
- @SmallTest
- public void testShouldBePendingAfterConnectAudio() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(false);
- mBluetoothManager.connectBluetoothAudio();
- verify(mHeadsetProxy).connectAudio();
- assertFalse(mBluetoothManager.isBluetoothAudioConnected());
- assertTrue(mBluetoothManager.isBluetoothAudioConnectedOrPending());
- }
-
- @SmallTest
- public void testDisconnectAudioWhenHeadsetServiceConnected() {
- mBluetoothManager.disconnectBluetoothAudio();
- verify(mHeadsetProxy).disconnectAudio();
- }
-
- @SmallTest
- public void testDisconnectAudioWithNoHeadsetService() {
- mBluetoothManager.setBluetoothHeadsetForTesting(null);
- mBluetoothManager.disconnectBluetoothAudio();
- verify(mHeadsetProxy, never()).disconnectAudio();
- }
-
- @SmallTest
- public void testConnectServiceWhenUninitialized1() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.<BluetoothDevice>emptyList());
- serviceListenerUnderTest.onServiceConnected(BluetoothProfile.HEALTH, null);
- verify(mListener).onBluetoothStateChange(BluetoothManager.BLUETOOTH_UNINITIALIZED,
- BluetoothManager.BLUETOOTH_DISCONNECTED);
- }
-
- @SmallTest
- public void testConnectServiceWhenUninitialized2() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(false);
- serviceListenerUnderTest.onServiceConnected(BluetoothProfile.HEALTH, null);
- verify(mListener).onBluetoothStateChange(BluetoothManager.BLUETOOTH_UNINITIALIZED,
- BluetoothManager.BLUETOOTH_DEVICE_CONNECTED);
- }
-
- @SmallTest
- public void testConnectServiceWhenUninitialized3() {
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(true);
- serviceListenerUnderTest.onServiceConnected(BluetoothProfile.HEALTH, null);
- verify(mListener).onBluetoothStateChange(BluetoothManager.BLUETOOTH_UNINITIALIZED,
- BluetoothManager.BLUETOOTH_AUDIO_CONNECTED);
- }
-
- @SmallTest
- public void testReceiveAudioDisconnectWhenConnected() {
- mBluetoothManager.setInternalBluetoothState(BluetoothManager.BLUETOOTH_AUDIO_CONNECTED);
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(false);
- receiverUnderTest.onReceive(mContext,
- buildAudioActionIntent(BluetoothHeadset.STATE_AUDIO_DISCONNECTED));
- verify(mListener).onBluetoothStateChange(BluetoothManager.BLUETOOTH_AUDIO_CONNECTED,
- BluetoothManager.BLUETOOTH_DEVICE_CONNECTED);
- }
-
- @SmallTest
- public void testReceiveAudioConnectWhenDisconnected() {
- mBluetoothManager.setInternalBluetoothState(BluetoothManager.BLUETOOTH_DEVICE_CONNECTED);
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(true);
- receiverUnderTest.onReceive(mContext,
- buildAudioActionIntent(BluetoothHeadset.STATE_AUDIO_CONNECTED));
- verify(mListener).onBluetoothStateChange(BluetoothManager.BLUETOOTH_DEVICE_CONNECTED,
- BluetoothManager.BLUETOOTH_AUDIO_CONNECTED);
- }
-
- @SmallTest
- public void testReceiveAudioConnectWhenPending() {
- mBluetoothManager.setInternalBluetoothState(BluetoothManager.BLUETOOTH_AUDIO_PENDING);
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(true);
- receiverUnderTest.onReceive(mContext,
- buildAudioActionIntent(BluetoothHeadset.STATE_AUDIO_CONNECTED));
- verify(mListener).onBluetoothStateChange(BluetoothManager.BLUETOOTH_AUDIO_PENDING,
- BluetoothManager.BLUETOOTH_AUDIO_CONNECTED);
- }
-
- @SmallTest
- public void testReceiveAudioDisconnectWhenPending() {
- mBluetoothManager.setInternalBluetoothState(BluetoothManager.BLUETOOTH_AUDIO_PENDING);
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(false);
- receiverUnderTest.onReceive(mContext,
- buildAudioActionIntent(BluetoothHeadset.STATE_AUDIO_DISCONNECTED));
- verify(mListener).onBluetoothStateChange(BluetoothManager.BLUETOOTH_AUDIO_PENDING,
- BluetoothManager.BLUETOOTH_DEVICE_CONNECTED);
- }
-
- @SmallTest
- public void testReceiveAudioConnectingWhenPending() {
- mBluetoothManager.setInternalBluetoothState(BluetoothManager.BLUETOOTH_AUDIO_PENDING);
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(
- Collections.singletonList(device1));
- when(mHeadsetProxy.isAudioConnected(eq(device1))).thenReturn(false);
- receiverUnderTest.onReceive(mContext,
- buildAudioActionIntent(BluetoothHeadset.STATE_AUDIO_CONNECTING));
- verify(mListener, never()).onBluetoothStateChange(anyInt(), anyInt());
- }
-
- private Intent buildAudioActionIntent(int state) {
- Intent i = new Intent(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
- i.putExtra(BluetoothHeadset.EXTRA_STATE, state);
- return i;
- }
-
- private void initializeDevice() {
- Parcel p1 = Parcel.obtain();
- p1.writeString("00:01:02:03:04:05");
- p1.setDataPosition(0);
- device1 = BluetoothDevice.CREATOR.createFromParcel(p1);
- p1.recycle();
- }
-}
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
index ecdf4b1..2b2caaf 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
@@ -153,7 +153,6 @@
public String messageDevice; // The device that should be specified in the message.
public ListenerUpdate[] expectedListenerUpdates; // what the listener should expect.
public int expectedBluetoothInteraction; // NONE, CONNECT, or DISCONNECT
- // TODO: this will always be none for now. Change once BT changes their API.
public String expectedConnectionAddress; // Expected device to connect to.
public String expectedFinalStateName; // Expected name of the final state.
public BluetoothDevice[] connectedDevices; // array of connected devices
@@ -230,7 +229,7 @@
setupConnectedDevices(new BluetoothDevice[]{device1}, null);
when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
nullable(ContentResolver.class))).thenReturn(0L);
- when(mHeadsetProxy.connectAudio()).thenReturn(false);
+ when(mHeadsetProxy.connectAudio(nullable(String.class))).thenReturn(false);
executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, null);
// Wait 3 times: for the first connection attempt, the retry attempt,
// the second retry, and once more to make sure there are only three attempts.
@@ -238,8 +237,7 @@
waitForStateMachineActionCompletion(sm, BluetoothRouteManager.RUN_RUNNABLE);
waitForStateMachineActionCompletion(sm, BluetoothRouteManager.RUN_RUNNABLE);
waitForStateMachineActionCompletion(sm, BluetoothRouteManager.RUN_RUNNABLE);
- // TODO: verify address
- verify(mHeadsetProxy, times(3)).connectAudio();
+ verify(mHeadsetProxy, times(3)).connectAudio(device1.getAddress());
assertEquals(BluetoothRouteManager.AUDIO_OFF_STATE_NAME, sm.getCurrentState().getName());
sm.getHandler().removeMessages(BluetoothRouteManager.CONNECTION_TIMEOUT);
sm.quitNow();
@@ -252,17 +250,16 @@
setupConnectedDevices(new BluetoothDevice[]{device1, device2}, null);
when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
nullable(ContentResolver.class))).thenReturn(0L);
- when(mHeadsetProxy.connectAudio()).thenReturn(false);
+ when(mHeadsetProxy.connectAudio(nullable(String.class))).thenReturn(false);
executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, device2.getAddress());
// Wait 3 times: the first connection attempt is accounted for in executeRoutingAction,
- // so wait twice for the retry attempt, again to make sure there are only two attempts, and
- // once more for good luck.
+ // so wait twice for the retry attempt, again to make sure there are only three attempts,
+ // and once more for good luck.
waitForStateMachineActionCompletion(sm, BluetoothRouteManager.RUN_RUNNABLE);
waitForStateMachineActionCompletion(sm, BluetoothRouteManager.RUN_RUNNABLE);
waitForStateMachineActionCompletion(sm, BluetoothRouteManager.RUN_RUNNABLE);
waitForStateMachineActionCompletion(sm, BluetoothRouteManager.RUN_RUNNABLE);
- // TODO: verify address of device2
- verify(mHeadsetProxy, times(3)).connectAudio();
+ verify(mHeadsetProxy, times(3)).connectAudio(device2.getAddress());
assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
+ ":" + device1.getAddress(),
sm.getCurrentState().getName());
@@ -279,15 +276,13 @@
BluetoothRouteManager.AUDIO_OFF_STATE_NAME, null);
setupConnectedDevices(new BluetoothDevice[]{device3, device2, device1}, null);
executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, device1.getAddress());
- // TODO: verify address
- verify(mHeadsetProxy, times(1)).connectAudio();
+ verify(mHeadsetProxy, times(1)).connectAudio(device1.getAddress());
setupConnectedDevices(new BluetoothDevice[]{device3, device2, device1}, device1);
executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, device1.getAddress());
executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, device2.getAddress());
- // TODO: verify address
- verify(mHeadsetProxy, times(2)).connectAudio();
+ verify(mHeadsetProxy, times(1)).connectAudio(device2.getAddress());
setupConnectedDevices(new BluetoothDevice[]{device3, device2, device1}, device2);
executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, device2.getAddress());
@@ -295,7 +290,7 @@
setupConnectedDevices(new BluetoothDevice[]{device3, device1}, null);
executeRoutingAction(sm, BluetoothRouteManager.LOST_DEVICE, device2.getAddress());
// Verify that we've fallen back to device 1
- verify(mHeadsetProxy, times(3)).connectAudio();
+ verify(mHeadsetProxy, times(2)).connectAudio(device1.getAddress());
assertEquals(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
+ ":" + device1.getAddress(),
sm.getCurrentState().getName());
@@ -309,7 +304,7 @@
setupConnectedDevices(new BluetoothDevice[]{device3}, null);
executeRoutingAction(sm, BluetoothRouteManager.LOST_DEVICE, device1.getAddress());
// Verify that we've fallen back to device 3
- verify(mHeadsetProxy, times(4)).connectAudio();
+ verify(mHeadsetProxy, times(1)).connectAudio(device3.getAddress());
assertEquals(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
+ ":" + device3.getAddress(),
sm.getCurrentState().getName());
@@ -332,8 +327,7 @@
BluetoothRouteManager.AUDIO_OFF_STATE_NAME, null);
setupConnectedDevices(new BluetoothDevice[]{device3, device2, device1}, null);
executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, device3.getAddress());
- // TODO: verify address
- verify(mHeadsetProxy, times(1)).connectAudio();
+ verify(mHeadsetProxy, times(1)).connectAudio(device3.getAddress());
setupConnectedDevices(new BluetoothDevice[]{device3, device2, device1}, device3);
executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, device3.getAddress());
@@ -342,7 +336,7 @@
setupConnectedDevices(new BluetoothDevice[]{device2, device1}, null);
executeRoutingAction(sm, BluetoothRouteManager.LOST_DEVICE, device3.getAddress());
// Verify that we've fallen back to device 2
- verify(mHeadsetProxy, times(2)).connectAudio();
+ verify(mHeadsetProxy, times(1)).connectAudio(device2.getAddress());
assertEquals(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
+ ":" + device2.getAddress(),
sm.getCurrentState().getName());
@@ -356,7 +350,7 @@
setupConnectedDevices(new BluetoothDevice[]{device1}, null);
executeRoutingAction(sm, BluetoothRouteManager.LOST_DEVICE, device2.getAddress());
// Verify that we've fallen back to device 1
- verify(mHeadsetProxy, times(3)).connectAudio();
+ verify(mHeadsetProxy, times(1)).connectAudio(device1.getAddress());
assertEquals(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
+ ":" + device1.getAddress(),
sm.getCurrentState().getName());
@@ -411,18 +405,17 @@
}
}
- // TODO: work the address in here
switch (params.expectedBluetoothInteraction) {
case NONE:
- verify(mHeadsetProxy, never()).connectAudio();
+ verify(mHeadsetProxy, never()).connectAudio(nullable(String.class));
verify(mHeadsetProxy, never()).disconnectAudio();
break;
case CONNECT:
- verify(mHeadsetProxy).connectAudio();
+ verify(mHeadsetProxy).connectAudio(params.expectedConnectionAddress);
verify(mHeadsetProxy, never()).disconnectAudio();
break;
case DISCONNECT:
- verify(mHeadsetProxy, never()).connectAudio();
+ verify(mHeadsetProxy, never()).connectAudio(nullable(String.class));
verify(mHeadsetProxy).disconnectAudio();
break;
}
@@ -465,7 +458,7 @@
waitForStateMachineActionCompletion(brm, CallAudioModeStateMachine.RUN_RUNNABLE);
}
- private BluetoothDevice makeBluetoothDevice(String address) {
+ public static BluetoothDevice makeBluetoothDevice(String address) {
Parcel p1 = Parcel.obtain();
p1.writeString(address);
p1.setDataPosition(0);
@@ -483,7 +476,7 @@
mTimeoutsAdapter = mock(Timeouts.Adapter.class);
}
when(mDeviceManager.getHeadsetService()).thenReturn(mHeadsetProxy);
- when(mHeadsetProxy.connectAudio()).thenReturn(true);
+ when(mHeadsetProxy.connectAudio(nullable(String.class))).thenReturn(true);
when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
nullable(ContentResolver.class))).thenReturn(100000L);
when(mTimeoutsAdapter.getBluetoothPendingTimeoutMillis(
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 9742021..84b75d1 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -16,6 +16,7 @@
package com.android.server.telecom.tests;
+import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.media.AudioManager;
import android.media.IAudioService;
@@ -43,6 +44,8 @@
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import static org.mockito.ArgumentMatchers.nullable;
@@ -63,14 +66,24 @@
private static final int ON = 1;
private static final int OFF = 2;
+ private static final BluetoothDevice bluetoothDevice1 =
+ BluetoothRouteManagerTest.makeBluetoothDevice("00:00:00:00:00:01");
+ private static final BluetoothDevice bluetoothDevice2 =
+ BluetoothRouteManagerTest.makeBluetoothDevice("00:00:00:00:00:02");
+ private static final BluetoothDevice bluetoothDevice3 =
+ BluetoothRouteManagerTest.makeBluetoothDevice("00:00:00:00:00:03");
+
static class RoutingTestParameters extends TestParameters {
public String name;
public int initialRoute;
+ public BluetoothDevice initialBluetoothDevice = null;
public int availableRoutes; // may excl. speakerphone, because that's always available
+ public List<BluetoothDevice> availableBluetoothDevices = Collections.emptyList();
public int speakerInteraction; // one of NONE, ON, or OFF
public int bluetoothInteraction; // one of NONE, ON, or OFF
public int action;
public int expectedRoute;
+ public BluetoothDevice expectedBluetoothDevice = null;
public int expectedAvailableRoutes; // also may exclude the speakerphone.
public boolean doesDeviceSupportEarpiece; // set to false in the case of Wear devices
public boolean shouldRunWithFocus;
@@ -99,6 +112,21 @@
return this;
}
+ public RoutingTestParameters setInitialBluetoothDevice(BluetoothDevice device) {
+ initialBluetoothDevice = device;
+ return this;
+ }
+
+ public RoutingTestParameters setAvailableBluetoothDevices(BluetoothDevice... devices) {
+ availableBluetoothDevices = Arrays.asList(devices);
+ return this;
+ }
+
+ public RoutingTestParameters setExpectedBluetoothDevice(BluetoothDevice device) {
+ expectedBluetoothDevice = device;
+ return this;
+ }
+
@Override
public String toString() {
return "RoutingTestParameters{" +
@@ -262,6 +290,8 @@
when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true);
+ when(mockBluetoothRouteManager.getConnectedDevices())
+ .thenReturn(Collections.singletonList(bluetoothDevice1));
when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false);
CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH,
@@ -272,12 +302,12 @@
CallAudioRouteStateMachine.RINGING_FOCUS);
waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
- verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null);
+ verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(nullable(String.class));
stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
CallAudioRouteStateMachine.ACTIVE_FOCUS);
waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
- verify(mockBluetoothRouteManager, times(1)).connectBluetoothAudio(null);
+ verify(mockBluetoothRouteManager, times(1)).connectBluetoothAudio(nullable(String.class));
}
@MediumTest
@@ -318,6 +348,53 @@
}
@SmallTest
+ public void testConnectSpecificBluetoothDevice() {
+ CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
+ mContext,
+ mockCallsManager,
+ mockBluetoothRouteManager,
+ mockWiredHeadsetManager,
+ mockStatusBarNotifier,
+ mAudioServiceFactory,
+ true);
+ List<BluetoothDevice> availableDevices =
+ Arrays.asList(bluetoothDevice1, bluetoothDevice2, bluetoothDevice3);
+
+ when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false);
+ when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
+ when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true);
+ when(mockBluetoothRouteManager.getConnectedDevices()).thenReturn(availableDevices);
+ doAnswer(invocation -> {
+ when(mockBluetoothRouteManager.getBluetoothAudioConnectedDevice())
+ .thenReturn(bluetoothDevice2);
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.BT_AUDIO_CONNECTED);
+ return null;
+ }).when(mockBluetoothRouteManager).connectBluetoothAudio(bluetoothDevice2.getAddress());
+
+ CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, null,
+ availableDevices);
+ stateMachine.initialize(initState);
+
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
+ CallAudioRouteStateMachine.ACTIVE_FOCUS);
+
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.USER_SWITCH_BLUETOOTH,
+ 0, bluetoothDevice2.getAddress());
+ waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
+
+ verify(mockBluetoothRouteManager).connectBluetoothAudio(bluetoothDevice2.getAddress());
+ waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
+ CallAudioState expectedEndState = new CallAudioState(false,
+ CallAudioState.ROUTE_BLUETOOTH,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH,
+ bluetoothDevice2,
+ availableDevices);
+
+ verifyNewSystemCallAudioState(initState, expectedEndState);
+ }
+
+ @SmallTest
public void testInitializationWithEarpieceNoHeadsetNoBluetooth() {
CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER);
@@ -846,15 +923,21 @@
switch (params.bluetoothInteraction) {
case NONE:
verify(mockBluetoothRouteManager, never()).disconnectBluetoothAudio();
- verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null);
+ verify(mockBluetoothRouteManager, never())
+ .connectBluetoothAudio(nullable(String.class));
break;
case ON:
- verify(mockBluetoothRouteManager).connectBluetoothAudio(null);
-
+ if (params.expectedBluetoothDevice == null) {
+ verify(mockBluetoothRouteManager).connectBluetoothAudio(null);
+ } else {
+ verify(mockBluetoothRouteManager).connectBluetoothAudio(
+ params.expectedBluetoothDevice.getAddress());
+ }
verify(mockBluetoothRouteManager, never()).disconnectBluetoothAudio();
break;
case OFF:
- verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null);
+ verify(mockBluetoothRouteManager, never())
+ .connectBluetoothAudio(nullable(String.class));
verify(mockBluetoothRouteManager).disconnectBluetoothAudio();
}
@@ -881,6 +964,14 @@
when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(
(params.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0
|| (params.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0);
+ when(mockBluetoothRouteManager.getConnectedDevices())
+ .thenReturn(params.availableBluetoothDevices);
+ if (params.initialBluetoothDevice != null) {
+ when(mockBluetoothRouteManager.getBluetoothAudioConnectedDevice())
+ .thenReturn(params.initialBluetoothDevice);
+ }
+
+
doAnswer(invocation -> {
sm.sendMessageWithSessionInfo(CallAudioRouteStateMachine.BT_AUDIO_CONNECTED);
return null;
@@ -938,7 +1029,7 @@
private void verifyNoSystemAudioChanges() {
verify(mockBluetoothRouteManager, never()).disconnectBluetoothAudio();
- verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null);
+ verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(nullable(String.class));
verify(mockAudioManager, never()).setSpeakerphoneOn(any(Boolean.class));
verify(mockCallsManager, never()).onCallAudioStateChanged(any(CallAudioState.class),
any(CallAudioState.class));