Snap for 4781566 from f44285a11239129ee93dec1ef97d96aa70df1e0a to pi-release
Change-Id: I36ef7ce5659826f3636a8cc91eae9dbfe67f054c
diff --git a/src/com/android/server/telecom/BluetoothHeadsetProxy.java b/src/com/android/server/telecom/BluetoothHeadsetProxy.java
index 7de49fc..f32f454 100644
--- a/src/com/android/server/telecom/BluetoothHeadsetProxy.java
+++ b/src/com/android/server/telecom/BluetoothHeadsetProxy.java
@@ -68,6 +68,10 @@
return mBluetoothHeadset.setActiveDevice(device);
}
+ public BluetoothDevice getActiveDevice() {
+ return mBluetoothHeadset.getActiveDevice();
+ }
+
public boolean isAudioOn() {
return mBluetoothHeadset.isAudioOn();
}
diff --git a/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java b/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java
index 32d737c..a871dfc 100644
--- a/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java
+++ b/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java
@@ -52,15 +52,15 @@
}
@Override
- public void onBluetoothDeviceAvailable() {
+ public void onBluetoothActiveDevicePresent() {
mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
- CallAudioRouteStateMachine.CONNECT_BLUETOOTH);
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT);
}
@Override
- public void onBluetoothDeviceUnavailable() {
+ public void onBluetoothActiveDeviceGone() {
mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH);
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE);
}
@Override
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index 8ea35be..d380bfd 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -91,11 +91,11 @@
/** Valid values for msg.what */
public static final int CONNECT_WIRED_HEADSET = 1;
public static final int DISCONNECT_WIRED_HEADSET = 2;
- public static final int CONNECT_BLUETOOTH = 3;
- public static final int DISCONNECT_BLUETOOTH = 4;
public static final int CONNECT_DOCK = 5;
public static final int DISCONNECT_DOCK = 6;
public static final int BLUETOOTH_DEVICE_LIST_CHANGED = 7;
+ public static final int BT_ACTIVE_DEVICE_PRESENT = 8;
+ public static final int BT_ACTIVE_DEVICE_GONE = 9;
public static final int SWITCH_EARPIECE = 1001;
public static final int SWITCH_BLUETOOTH = 1002;
@@ -151,11 +151,11 @@
private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{
put(CONNECT_WIRED_HEADSET, "CONNECT_WIRED_HEADSET");
put(DISCONNECT_WIRED_HEADSET, "DISCONNECT_WIRED_HEADSET");
- put(CONNECT_BLUETOOTH, "CONNECT_BLUETOOTH");
- put(DISCONNECT_BLUETOOTH, "DISCONNECT_BLUETOOTH");
put(CONNECT_DOCK, "CONNECT_DOCK");
put(DISCONNECT_DOCK, "DISCONNECT_DOCK");
put(BLUETOOTH_DEVICE_LIST_CHANGED, "BLUETOOTH_DEVICE_LIST_CHANGED");
+ put(BT_ACTIVE_DEVICE_PRESENT, "BT_ACTIVE_DEVICE_PRESENT");
+ put(BT_ACTIVE_DEVICE_GONE, "BT_ACTIVE_DEVICE_GONE");
put(SWITCH_EARPIECE, "SWITCH_EARPIECE");
put(SWITCH_BLUETOOTH, "SWITCH_BLUETOOTH");
@@ -242,6 +242,8 @@
int removedRoutes = 0;
boolean isHandled = NOT_HANDLED;
+ Log.i(this, "Processing message %s",
+ MESSAGE_CODE_TO_NAME.get(msg.what, Integer.toString(msg.what)));
switch (msg.what) {
case CONNECT_WIRED_HEADSET:
Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
@@ -249,11 +251,6 @@
removedRoutes |= ROUTE_EARPIECE;
addedRoutes |= ROUTE_WIRED_HEADSET;
break;
- case CONNECT_BLUETOOTH:
- Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
- "Bluetooth connected");
- addedRoutes |= ROUTE_BLUETOOTH;
- break;
case DISCONNECT_WIRED_HEADSET:
Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
"Wired headset disconnected");
@@ -262,10 +259,13 @@
addedRoutes |= ROUTE_EARPIECE;
}
break;
- case DISCONNECT_BLUETOOTH:
+ case BT_ACTIVE_DEVICE_PRESENT:
Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
- "Bluetooth disconnected");
- removedRoutes |= ROUTE_BLUETOOTH;
+ "Bluetooth active device present");
+ break;
+ case BT_ACTIVE_DEVICE_GONE:
+ Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
+ "Bluetooth active device gone");
break;
case BLUETOOTH_DEVICE_LIST_CHANGED:
Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
@@ -493,7 +493,7 @@
case CONNECT_WIRED_HEADSET:
sendInternalMessage(SWITCH_HEADSET);
return HANDLED;
- case CONNECT_BLUETOOTH:
+ case BT_ACTIVE_DEVICE_PRESENT:
if (!mHasUserExplicitlyLeftBluetooth) {
sendInternalMessage(SWITCH_BLUETOOTH);
} else {
@@ -501,7 +501,7 @@
"explicitly disconnected.");
}
return HANDLED;
- case DISCONNECT_BLUETOOTH:
+ case BT_ACTIVE_DEVICE_GONE:
// No change in audio route required
return HANDLED;
case DISCONNECT_WIRED_HEADSET:
@@ -688,7 +688,7 @@
Log.e(this, new IllegalStateException(),
"Wired headset should already be connected.");
return HANDLED;
- case CONNECT_BLUETOOTH:
+ case BT_ACTIVE_DEVICE_PRESENT:
if (!mHasUserExplicitlyLeftBluetooth) {
sendInternalMessage(SWITCH_BLUETOOTH);
} else {
@@ -696,7 +696,7 @@
"explicitly disconnected.");
}
return HANDLED;
- case DISCONNECT_BLUETOOTH:
+ case BT_ACTIVE_DEVICE_GONE:
// No change in audio route required
return HANDLED;
case DISCONNECT_WIRED_HEADSET:
@@ -1000,12 +1000,11 @@
case CONNECT_WIRED_HEADSET:
sendInternalMessage(SWITCH_HEADSET);
return HANDLED;
- case CONNECT_BLUETOOTH:
- // We can't tell when a change in bluetooth state corresponds to an
- // actual connection or disconnection, so we'll just ignore it if we're already
- // in the bluetooth route.
+ case BT_ACTIVE_DEVICE_PRESENT:
+ Log.w(this, "Bluetooth active device should not"
+ + " have been null while we were in BT route.");
return HANDLED;
- case DISCONNECT_BLUETOOTH:
+ case BT_ACTIVE_DEVICE_GONE:
sendInternalMessage(SWITCH_BASELINE_ROUTE, NO_INCLUDE_BLUETOOTH_IN_BASELINE);
mWasOnSpeaker = false;
return HANDLED;
@@ -1204,7 +1203,7 @@
case CONNECT_WIRED_HEADSET:
sendInternalMessage(SWITCH_HEADSET);
return HANDLED;
- case CONNECT_BLUETOOTH:
+ case BT_ACTIVE_DEVICE_PRESENT:
if (!mHasUserExplicitlyLeftBluetooth) {
sendInternalMessage(SWITCH_BLUETOOTH);
} else {
@@ -1212,7 +1211,7 @@
"explicitly disconnected.");
}
return HANDLED;
- case DISCONNECT_BLUETOOTH:
+ case BT_ACTIVE_DEVICE_GONE:
// No change in audio route required
return HANDLED;
case DISCONNECT_WIRED_HEADSET:
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index d50ef1a..ce35587 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -18,6 +18,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
index 8c3a694..298129a 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
@@ -72,8 +72,8 @@
public interface BluetoothStateListener {
void onBluetoothDeviceListChanged();
- void onBluetoothDeviceAvailable();
- void onBluetoothDeviceUnavailable();
+ void onBluetoothActiveDevicePresent();
+ void onBluetoothActiveDeviceGone();
void onBluetoothAudioConnected();
void onBluetoothAudioDisconnected();
}
@@ -243,15 +243,8 @@
break;
case LOST_DEVICE:
removeDevice((String) args.arg2);
-
if (Objects.equals(address, mDeviceAddress)) {
- String newAddress = connectHfpAudio(null);
- if (newAddress != null) {
- transitionTo(getConnectingStateForAddress(newAddress,
- "AudioConnecting/LOST_DEVICE"));
- } else {
- transitionTo(mAudioOffState);
- }
+ transitionToActualState();
}
break;
case CONNECT_HFP:
@@ -364,13 +357,7 @@
case LOST_DEVICE:
removeDevice((String) args.arg2);
if (Objects.equals(address, mDeviceAddress)) {
- String newAddress = connectHfpAudio(null);
- if (newAddress != null) {
- transitionTo(getConnectingStateForAddress(newAddress,
- "AudioConnected/LOST_DEVICE"));
- } else {
- transitionTo(mAudioOffState);
- }
+ transitionToActualState();
}
break;
case CONNECT_HFP:
@@ -421,14 +408,7 @@
case HFP_LOST:
if (Objects.equals(mDeviceAddress, address)) {
Log.i(LOG_TAG, "HFP connection with device %s lost.", mDeviceAddress);
- String nextAddress = connectHfpAudio(null, mDeviceAddress);
- if (nextAddress == null) {
- Log.i(LOG_TAG, "No suitable fallback device. Going to AUDIO_OFF.");
- transitionToActualState();
- } else {
- transitionTo(getConnectingStateForAddress(nextAddress,
- "AudioConnected/HFP_LOST"));
- }
+ transitionToActualState();
} else {
Log.w(LOG_TAG, "Got HFP lost message for device %s while" +
" connected to %s.", address, mDeviceAddress);
@@ -458,6 +438,8 @@
private BluetoothStateListener mListener;
private BluetoothDeviceManager mDeviceManager;
+ // Tracks the active device in the BT stack.
+ private BluetoothDevice mActiveDeviceCache = null;
public BluetoothRouteManager(Context context, TelecomSystem.SyncRoot lock,
BluetoothDeviceManager deviceManager, Timeouts.Adapter timeoutsAdapter) {
@@ -565,9 +547,6 @@
sendMessage(NEW_DEVICE_CONNECTED, args);
mListener.onBluetoothDeviceListChanged();
- if (mDeviceManager.getConnectedDevices().size() == 1) {
- mListener.onBluetoothDeviceAvailable();
- }
}
public void onDeviceLost(String lostDeviceAddress) {
@@ -577,8 +556,17 @@
sendMessage(LOST_DEVICE, args);
mListener.onBluetoothDeviceListChanged();
- if (mDeviceManager.getConnectedDevices().size() == 0) {
- mListener.onBluetoothDeviceUnavailable();
+ }
+
+ public void onActiveDeviceChanged(BluetoothDevice device) {
+ BluetoothDevice oldActiveDevice = mActiveDeviceCache;
+ mActiveDeviceCache = device;
+ if ((oldActiveDevice == null) ^ (device == null)) {
+ if (device == null) {
+ mListener.onBluetoothActiveDeviceGone();
+ } else {
+ mListener.onBluetoothActiveDevicePresent();
+ }
}
}
@@ -588,15 +576,7 @@
}
private String connectHfpAudio(String address) {
- return connectHfpAudio(address, 0, null);
- }
-
- private String connectHfpAudio(String address, int retryCount) {
- return connectHfpAudio(address, retryCount, null);
- }
-
- private String connectHfpAudio(String address, String excludeAddress) {
- return connectHfpAudio(address, 0, excludeAddress);
+ return connectHfpAudio(address, 0);
}
/**
@@ -605,23 +585,26 @@
* Telecom from within it.
* @param address The address that should be tried first. May be null.
* @param retryCount The number of times this connection attempt has been retried.
- * @param excludeAddress Don't connect to this address.
* @return The address of the device that's actually being connected to, or null if no
* connection was successful.
*/
- private String connectHfpAudio(String address, int retryCount, String excludeAddress) {
+ private String connectHfpAudio(String address, int retryCount) {
Collection<BluetoothDevice> deviceList = getConnectedDevices();
Optional<BluetoothDevice> matchingDevice = deviceList.stream()
.filter(d -> Objects.equals(d.getAddress(), address))
.findAny();
- String actualAddress = matchingDevice.isPresent() ?
- address : getPreferredDevice(excludeAddress);
+ String actualAddress = matchingDevice.isPresent()
+ ? address : getActiveDeviceAddress();
if (!matchingDevice.isPresent()) {
Log.i(this, "No device with address %s available. Using %s instead.",
address, actualAddress);
}
- if (actualAddress != null && !connectAudio(actualAddress)) {
+ if (actualAddress == null) {
+ Log.i(this, "No device specified and BT stack has no active device. Not connecting.");
+ return null;
+ }
+ if (!connectAudio(actualAddress)) {
boolean shouldRetry = retryCount < MAX_CONNECTION_RETRIES;
Log.w(LOG_TAG, "Could not connect to %s. Will %s", actualAddress,
shouldRetry ? "retry" : "not retry");
@@ -640,17 +623,8 @@
return actualAddress;
}
- private String getPreferredDevice(String excludeAddress) {
- String preferredDevice = null;
- for (String address : mMostRecentlyUsedDevices) {
- if (!Objects.equals(excludeAddress, address)) {
- preferredDevice = address;
- }
- }
- if (preferredDevice == null) {
- return mDeviceManager.getMostRecentlyConnectedDevice(excludeAddress);
- }
- return preferredDevice;
+ private String getActiveDeviceAddress() {
+ return mActiveDeviceCache == null ? null : mActiveDeviceCache.getAddress();
}
private void transitionToActualState() {
@@ -808,4 +782,9 @@
break;
}
}
+
+ @VisibleForTesting
+ public void setActiveDeviceCacheForTesting(BluetoothDevice device) {
+ mActiveDeviceCache = device;
+ }
}
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index 802fba0..f9c6437 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -38,6 +38,7 @@
INTENT_FILTER = new IntentFilter();
INTENT_FILTER.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
INTENT_FILTER.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
+ INTENT_FILTER.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
}
// If not in a call, BSR won't listen to the Bluetooth stack's HFP on/off messages, since
@@ -50,66 +51,84 @@
Log.startSession("BSR.oR");
try {
String action = intent.getAction();
-
- if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
- if (!mIsInCall) {
- Log.i(LOG_TAG, "Ignoring BT audio state change since we're not in a call");
- return;
- }
- int bluetoothHeadsetAudioState =
- intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
- BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
- BluetoothDevice device =
- intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (device == null) {
- Log.w(LOG_TAG, "Got null device from broadcast. " +
- "Ignoring.");
- return;
- }
-
- Log.i(LOG_TAG, "Device %s transitioned to audio state %d",
- device.getAddress(), bluetoothHeadsetAudioState);
- Session session = Log.createSubsession();
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = session;
- args.arg2 = device.getAddress();
- switch (bluetoothHeadsetAudioState) {
- case BluetoothHeadset.STATE_AUDIO_CONNECTED:
- mBluetoothRouteManager.sendMessage(HFP_IS_ON, args);
- break;
- case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
- mBluetoothRouteManager.sendMessage(HFP_LOST, args);
- break;
- }
- }
-
- else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
- int bluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
- BluetoothHeadset.STATE_DISCONNECTED);
- BluetoothDevice device =
- intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
- if (device == null) {
- Log.w(LOG_TAG, "Got null device from broadcast. " +
- "Ignoring.");
- return;
- }
-
- Log.i(LOG_TAG, "Device %s changed state to %d",
- device.getAddress(), bluetoothHeadsetState);
-
- if (bluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED) {
- mBluetoothDeviceManager.onDeviceConnected(device);
- } else if (bluetoothHeadsetState == BluetoothHeadset.STATE_DISCONNECTED
- || bluetoothHeadsetState == BluetoothHeadset.STATE_DISCONNECTING) {
- mBluetoothDeviceManager.onDeviceDisconnected(device);
- }
+ switch (action) {
+ case BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED:
+ handleAudioStateChanged(intent);
+ break;
+ case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
+ handleConnectionStateChanged(intent);
+ break;
+ case BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED:
+ handleActiveDeviceChanged(intent);
+ break;
}
} finally {
Log.endSession();
}
}
+ private void handleAudioStateChanged(Intent intent) {
+ if (!mIsInCall) {
+ Log.i(LOG_TAG, "Ignoring BT audio state change since we're not in a call");
+ return;
+ }
+ int bluetoothHeadsetAudioState =
+ intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
+ BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
+ BluetoothDevice device =
+ intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if (device == null) {
+ Log.w(LOG_TAG, "Got null device from broadcast. " +
+ "Ignoring.");
+ return;
+ }
+
+ Log.i(LOG_TAG, "Device %s transitioned to audio state %d",
+ device.getAddress(), bluetoothHeadsetAudioState);
+ Session session = Log.createSubsession();
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = session;
+ args.arg2 = device.getAddress();
+ switch (bluetoothHeadsetAudioState) {
+ case BluetoothHeadset.STATE_AUDIO_CONNECTED:
+ mBluetoothRouteManager.sendMessage(HFP_IS_ON, args);
+ break;
+ case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
+ mBluetoothRouteManager.sendMessage(HFP_LOST, args);
+ break;
+ }
+ }
+
+ private void handleConnectionStateChanged(Intent intent) {
+ int bluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
+ BluetoothHeadset.STATE_DISCONNECTED);
+ BluetoothDevice device =
+ intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+ if (device == null) {
+ Log.w(LOG_TAG, "Got null device from broadcast. " +
+ "Ignoring.");
+ return;
+ }
+
+ Log.i(LOG_TAG, "Device %s changed state to %d",
+ device.getAddress(), bluetoothHeadsetState);
+
+ if (bluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED) {
+ mBluetoothDeviceManager.onDeviceConnected(device);
+ } else if (bluetoothHeadsetState == BluetoothHeadset.STATE_DISCONNECTED
+ || bluetoothHeadsetState == BluetoothHeadset.STATE_DISCONNECTING) {
+ mBluetoothDeviceManager.onDeviceDisconnected(device);
+ }
+ }
+
+ private void handleActiveDeviceChanged(Intent intent) {
+ BluetoothDevice device =
+ intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ Log.i(LOG_TAG, "Device %s is now the preferred HFP device", device);
+ mBluetoothRouteManager.onActiveDeviceChanged(device);
+ }
+
public BluetoothStateReceiver(BluetoothDeviceManager deviceManager,
BluetoothRouteManager routeManager) {
mBluetoothDeviceManager = deviceManager;
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
index 5cf4c1d..30848f8 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
@@ -75,7 +75,7 @@
when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
nullable(ContentResolver.class))).thenReturn(0L);
when(mHeadsetProxy.connectAudio()).thenReturn(false);
- executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, null);
+ executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, DEVICE1.getAddress());
// 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.
waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -113,105 +113,6 @@
sm.quitNow();
}
- @SmallTest
- @Test
- public void testProperFallbackOrder1() {
- // Device 1, 2, 3 are connected in that order. Device 1 is activated, then device 2.
- // Disconnect device 2, verify fallback to device 1. Disconnect device 1, fallback to
- // device 3.
- BluetoothRouteManager sm = setupStateMachine(
- BluetoothRouteManager.AUDIO_OFF_STATE_NAME, null);
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3, DEVICE2, DEVICE1}, null);
- executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, DEVICE1.getAddress());
- verifyConnectionAttempt(DEVICE1, 1);
-
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3, DEVICE2, DEVICE1}, DEVICE1);
- executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, DEVICE1.getAddress());
-
- executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, DEVICE2.getAddress());
- verifyConnectionAttempt(DEVICE2, 1);
-
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3, DEVICE2, DEVICE1}, DEVICE2);
- executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, DEVICE2.getAddress());
- // Disconnect device 2
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3, DEVICE1}, null);
- executeRoutingAction(sm, BluetoothRouteManager.LOST_DEVICE, DEVICE2.getAddress());
- // Verify that we've fallen back to device 1
- verifyConnectionAttempt(DEVICE1, 2);
- assertEquals(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
- + ":" + DEVICE1.getAddress(),
- sm.getCurrentState().getName());
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3, DEVICE1}, DEVICE1);
- executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, DEVICE1.getAddress());
- assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
- + ":" + DEVICE1.getAddress(),
- sm.getCurrentState().getName());
-
- // Disconnect device 1
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3}, null);
- executeRoutingAction(sm, BluetoothRouteManager.LOST_DEVICE, DEVICE1.getAddress());
- // Verify that we've fallen back to device 3
- verifyConnectionAttempt(DEVICE3, 1);
- assertEquals(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
- + ":" + DEVICE3.getAddress(),
- sm.getCurrentState().getName());
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3}, DEVICE3);
- executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, DEVICE3.getAddress());
- assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
- + ":" + DEVICE3.getAddress(),
- sm.getCurrentState().getName());
-
- sm.getHandler().removeMessages(BluetoothRouteManager.CONNECTION_TIMEOUT);
- sm.quitNow();
- }
-
- @SmallTest
- @Test
- public void testProperFallbackOrder2() {
- // Device 1, 2, 3 are connected in that order. Device 3 is activated.
- // Disconnect device 3, verify fallback to device 2. Disconnect device 2, fallback to
- // device 1.
- BluetoothRouteManager sm = setupStateMachine(
- BluetoothRouteManager.AUDIO_OFF_STATE_NAME, null);
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3, DEVICE2, DEVICE1}, null);
- executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, DEVICE3.getAddress());
- verifyConnectionAttempt(DEVICE3, 1);
-
- setupConnectedDevices(new BluetoothDevice[]{DEVICE3, DEVICE2, DEVICE1}, DEVICE3);
- executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, DEVICE3.getAddress());
-
- // Disconnect device 2
- setupConnectedDevices(new BluetoothDevice[]{DEVICE2, DEVICE1}, null);
- executeRoutingAction(sm, BluetoothRouteManager.LOST_DEVICE, DEVICE3.getAddress());
- // Verify that we've fallen back to device 2
- verifyConnectionAttempt(DEVICE2, 1);
- assertEquals(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
- + ":" + DEVICE2.getAddress(),
- sm.getCurrentState().getName());
- setupConnectedDevices(new BluetoothDevice[]{DEVICE2, DEVICE1}, DEVICE2);
- executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, DEVICE2.getAddress());
- assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
- + ":" + DEVICE2.getAddress(),
- sm.getCurrentState().getName());
-
- // Disconnect device 2
- setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null);
- executeRoutingAction(sm, BluetoothRouteManager.LOST_DEVICE, DEVICE2.getAddress());
- // Verify that we've fallen back to device 1
- verifyConnectionAttempt(DEVICE1, 1);
- assertEquals(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
- + ":" + DEVICE1.getAddress(),
- sm.getCurrentState().getName());
- setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, DEVICE1);
- executeRoutingAction(sm, BluetoothRouteManager.HFP_IS_ON, DEVICE1.getAddress());
- assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
- + ":" + DEVICE1.getAddress(),
- sm.getCurrentState().getName());
-
- sm.getHandler().removeMessages(BluetoothRouteManager.CONNECTION_TIMEOUT);
- sm.quitNow();
- }
-
private BluetoothRouteManager setupStateMachine(String initialState,
BluetoothDevice initialDevice) {
resetMocks();
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
index bf35506..b9c1427 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
@@ -54,7 +54,7 @@
@RunWith(Parameterized.class)
public class BluetoothRouteTransitionTests extends TelecomTestCase {
private enum ListenerUpdate {
- DEVICE_LIST_CHANGED, DEVICE_AVAILABLE, DEVICE_UNAVAILABLE,
+ DEVICE_LIST_CHANGED, ACTIVE_DEVICE_PRESENT, ACTIVE_DEVICE_GONE,
AUDIO_CONNECTED, AUDIO_DISCONNECTED
}
@@ -70,6 +70,8 @@
private BluetoothDevice expectedConnectionDevice;
private String expectedFinalStateName;
private BluetoothDevice[] connectedDevices;
+ // the active device as returned by BluetoothHeadset#getActiveDevice
+ private BluetoothDevice activeDevice = null;
public BluetoothRouteTestParametersBuilder setName(String name) {
this.name = name;
@@ -133,6 +135,11 @@
return this;
}
+ public BluetoothRouteTestParametersBuilder setActiveDevice(BluetoothDevice device) {
+ this.activeDevice = device;
+ return this;
+ }
+
public BluetoothRouteTestParameters build() {
return new BluetoothRouteTestParameters(name,
initialBluetoothState,
@@ -144,7 +151,9 @@
expectedFinalStateName,
connectedDevices,
messageDevice,
- audioOnDevice);
+ audioOnDevice,
+ activeDevice);
+
}
}
@@ -160,13 +169,15 @@
public BluetoothDevice expectedConnectionDevice; // Expected device to connect to.
public String expectedFinalStateName; // Expected name of the final state.
public BluetoothDevice[] connectedDevices; // array of connected devices
+ // the active device as returned by BluetoothHeadset#getActiveDevice
+ private BluetoothDevice activeDevice = null;
public BluetoothRouteTestParameters(String name, String initialBluetoothState,
BluetoothDevice initialDevice, int messageType, ListenerUpdate[]
expectedListenerUpdates, int expectedBluetoothInteraction, BluetoothDevice
expectedConnectionDevice, String expectedFinalStateName,
BluetoothDevice[] connectedDevices, BluetoothDevice messageDevice,
- BluetoothDevice audioOnDevice) {
+ BluetoothDevice audioOnDevice, BluetoothDevice activeDevice) {
this.name = name;
this.initialBluetoothState = initialBluetoothState;
this.initialDevice = initialDevice;
@@ -178,6 +189,7 @@
this.connectedDevices = connectedDevices;
this.messageDevice = messageDevice;
this.audioOnDevice = audioOnDevice;
+ this.activeDevice = activeDevice;
}
@Override
@@ -193,6 +205,7 @@
", expectedConnectionDevice='" + expectedConnectionDevice + '\'' +
", expectedFinalStateName='" + expectedFinalStateName + '\'' +
", connectedDevices=" + Arrays.toString(connectedDevices) +
+ ", activeDevice='" + activeDevice + '\'' +
'}';
}
}
@@ -225,13 +238,17 @@
BluetoothRouteManager sm = setupStateMachine(
mParams.initialBluetoothState, mParams.initialDevice);
- setupConnectedDevices(mParams.connectedDevices, mParams.audioOnDevice);
+ setupConnectedDevices(mParams.connectedDevices,
+ mParams.audioOnDevice, mParams.activeDevice);
+ sm.setActiveDeviceCacheForTesting(mParams.activeDevice);
// Go through the utility methods for these two messages
if (mParams.messageType == BluetoothRouteManager.NEW_DEVICE_CONNECTED) {
sm.onDeviceAdded(mParams.messageDevice.getAddress());
+ sm.onActiveDeviceChanged(mParams.messageDevice);
} else if (mParams.messageType == BluetoothRouteManager.LOST_DEVICE) {
sm.onDeviceLost(mParams.messageDevice.getAddress());
+ sm.onActiveDeviceChanged(null);
} else {
executeRoutingAction(sm, mParams.messageType,
mParams.messageDevice == null ? null : mParams.messageDevice.getAddress());
@@ -245,11 +262,11 @@
case DEVICE_LIST_CHANGED:
verify(mListener).onBluetoothDeviceListChanged();
break;
- case DEVICE_AVAILABLE:
- verify(mListener).onBluetoothDeviceAvailable();
+ case ACTIVE_DEVICE_PRESENT:
+ verify(mListener).onBluetoothActiveDevicePresent();
break;
- case DEVICE_UNAVAILABLE:
- verify(mListener).onBluetoothDeviceUnavailable();
+ case ACTIVE_DEVICE_GONE:
+ verify(mListener).onBluetoothActiveDeviceGone();
break;
case AUDIO_CONNECTED:
verify(mListener).onBluetoothAudioConnected();
@@ -282,12 +299,14 @@
sm.quitNow();
}
- private void setupConnectedDevices(BluetoothDevice[] devices, BluetoothDevice activeDevice) {
+ private void setupConnectedDevices(BluetoothDevice[] devices,
+ BluetoothDevice audioOnDevice, BluetoothDevice activeDevice) {
when(mDeviceManager.getNumConnectedDevices()).thenReturn(devices.length);
when(mDeviceManager.getConnectedDevices()).thenReturn(Arrays.asList(devices));
when(mHeadsetProxy.getConnectedDevices()).thenReturn(Arrays.asList(devices));
- if (activeDevice != null) {
- when(mHeadsetProxy.isAudioConnected(eq(activeDevice))).thenReturn(true);
+ when(mHeadsetProxy.getActiveDevice()).thenReturn(activeDevice);
+ if (audioOnDevice != null) {
+ when(mHeadsetProxy.isAudioConnected(eq(audioOnDevice))).thenReturn(true);
}
doAnswer(invocation -> {
BluetoothDevice first = getFirstExcluding(devices,
@@ -342,23 +361,25 @@
.setConnectedDevices(DEVICE1)
.setMessageType(BluetoothRouteManager.NEW_DEVICE_CONNECTED)
.setMessageDevice(DEVICE1)
- .setExpectedListenerUpdates(ListenerUpdate.DEVICE_AVAILABLE)
+ .setExpectedListenerUpdates(ListenerUpdate.DEVICE_LIST_CHANGED,
+ ListenerUpdate.ACTIVE_DEVICE_PRESENT)
.setExpectedBluetoothInteraction(NONE)
.setExpectedConnectionDevice(null)
.setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
.build());
result.add(new BluetoothRouteTestParametersBuilder()
- .setName("Nonspecific connection request while audio off.")
+ .setName("Nonspecific connection request while audio off with BT-active device")
.setInitialBluetoothState(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
.setInitialDevice(null)
.setConnectedDevices(DEVICE2, DEVICE1)
+ .setActiveDevice(DEVICE1)
.setMessageType(BluetoothRouteManager.CONNECT_HFP)
.setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED)
.setExpectedBluetoothInteraction(CONNECT)
- .setExpectedConnectionDevice(DEVICE2)
+ .setExpectedConnectionDevice(DEVICE1)
.setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
- + ":" + DEVICE2)
+ + ":" + DEVICE1)
.build());
result.add(new BluetoothRouteTestParametersBuilder()
@@ -390,21 +411,21 @@
.build());
result.add(new BluetoothRouteTestParametersBuilder()
- .setName("Device loses HFP audio but remains connected. Fallback.")
+ .setName("Device loses HFP audio but remains connected."
+ + " No fallback even though other devices available.")
.setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
.setInitialDevice(DEVICE2)
.setConnectedDevices(DEVICE2, DEVICE1, DEVICE3)
.setMessageType(BluetoothRouteManager.HFP_LOST)
.setMessageDevice(DEVICE2)
- .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED)
- .setExpectedBluetoothInteraction(CONNECT)
- .setExpectedConnectionDevice(DEVICE1)
- .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
- + ":" + DEVICE1)
+ .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED)
+ .setExpectedBluetoothInteraction(NONE)
+ .setExpectedConnectionDevice(null)
+ .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
.build());
result.add(new BluetoothRouteTestParametersBuilder()
- .setName("Switch active devices")
+ .setName("Switch the device that audio is being routed to")
.setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
.setInitialDevice(DEVICE2)
.setConnectedDevices(DEVICE2, DEVICE1, DEVICE3)
@@ -435,29 +456,30 @@
.setName("Device gets disconnected while active. No fallback.")
.setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
.setInitialDevice(DEVICE2)
+ .setActiveDevice(DEVICE2)
.setConnectedDevices()
.setMessageType(BluetoothRouteManager.LOST_DEVICE)
.setMessageDevice(DEVICE2)
.setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED,
- ListenerUpdate.DEVICE_LIST_CHANGED, ListenerUpdate.DEVICE_UNAVAILABLE)
+ ListenerUpdate.DEVICE_LIST_CHANGED, ListenerUpdate.ACTIVE_DEVICE_GONE)
.setExpectedBluetoothInteraction(NONE)
.setExpectedConnectionDevice(null)
.setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
.build());
result.add(new BluetoothRouteTestParametersBuilder()
- .setName("Device gets disconnected while active. Fallback.")
+ .setName("Device gets disconnected while active."
+ + " No fallback even though other devices available.")
.setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
.setInitialDevice(DEVICE2)
.setConnectedDevices(DEVICE3)
.setMessageType(BluetoothRouteManager.LOST_DEVICE)
.setMessageDevice(DEVICE2)
- .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED,
+ .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED,
ListenerUpdate.DEVICE_LIST_CHANGED)
- .setExpectedBluetoothInteraction(CONNECT)
- .setExpectedConnectionDevice(DEVICE3)
- .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
- + ":" + DEVICE3)
+ .setExpectedBluetoothInteraction(NONE)
+ .setExpectedConnectionDevice(null)
+ .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
.build());
result.add(new BluetoothRouteTestParametersBuilder()
@@ -488,18 +510,17 @@
.build());
result.add(new BluetoothRouteTestParametersBuilder()
- .setName("Device gets disconnected while pending. Fallback.")
+ .setName("Device gets disconnected while pending."
+ + " No fallback even though other devices available.")
.setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX)
.setInitialDevice(DEVICE2)
.setConnectedDevices(DEVICE3)
.setMessageType(BluetoothRouteManager.LOST_DEVICE)
.setMessageDevice(DEVICE2)
- .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED,
+ .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED,
ListenerUpdate.DEVICE_LIST_CHANGED)
- .setExpectedBluetoothInteraction(CONNECT)
- .setExpectedConnectionDevice(DEVICE3)
- .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
- + ":" + DEVICE3)
+ .setExpectedBluetoothInteraction(NONE)
+ .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
.build());
result.add(new BluetoothRouteTestParametersBuilder()
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index d4c3d1d..6330996 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -212,9 +212,9 @@
verifyNewSystemCallAudioState(initState, expectedEndState);
resetMocks();
stateMachine.sendMessageWithSessionInfo(
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH);
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE);
stateMachine.sendMessageWithSessionInfo(
- CallAudioRouteStateMachine.CONNECT_BLUETOOTH);
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT);
waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState());
@@ -280,11 +280,11 @@
verifyNewSystemCallAudioState(expectedMidState, expectedEndState);
stateMachine.sendMessageWithSessionInfo(
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH);
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE);
when(mockBluetoothRouteManager.getBluetoothAudioConnectedDevice())
.thenReturn(null);
stateMachine.sendMessageWithSessionInfo(
- CallAudioRouteStateMachine.CONNECT_BLUETOOTH);
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT);
waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
// second wait needed for the BT_AUDIO_CONNECTED message
@@ -359,7 +359,8 @@
.thenReturn(Collections.singletonList(bluetoothDevice1));
stateMachine.sendMessageWithSessionInfo(
CallAudioRouteStateMachine.BLUETOOTH_DEVICE_LIST_CHANGED);
- stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.CONNECT_BLUETOOTH);
+ stateMachine.sendMessageWithSessionInfo(
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT);
waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null);
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
index 609a488..19630b1 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
@@ -71,6 +71,12 @@
private static final int OFF = 2;
private static final int OPTIONAL = 3;
+ // This is used to simulate the first bluetooth device getting connected --
+ // it requires two messages: BT device list changed and active device present
+ private static final int SPECIAL_CONNECT_BT_ACTION = 998;
+ // Same, but for disconnection
+ private static final int SPECIAL_DISCONNECT_BT_ACTION = 999;
+
static class RoutingTestParameters {
public String name;
public int initialRoute;
@@ -208,6 +214,26 @@
when(fakeCall.getSupportedAudioRoutes()).thenReturn(params.callSupportedRoutes);
}
+ private void sendActionToStateMachine(CallAudioRouteStateMachine sm) {
+ switch (mParams.action) {
+ case SPECIAL_CONNECT_BT_ACTION:
+ sm.sendMessageWithSessionInfo(
+ CallAudioRouteStateMachine.BLUETOOTH_DEVICE_LIST_CHANGED);
+ sm.sendMessageWithSessionInfo(
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT);
+ break;
+ case SPECIAL_DISCONNECT_BT_ACTION:
+ sm.sendMessageWithSessionInfo(
+ CallAudioRouteStateMachine.BLUETOOTH_DEVICE_LIST_CHANGED);
+ sm.sendMessageWithSessionInfo(
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE);
+ break;
+ default:
+ sm.sendMessageWithSessionInfo(mParams.action);
+ break;
+ }
+ }
+
@Test
@SmallTest
public void testActiveTransition() {
@@ -225,7 +251,8 @@
// Set the initial CallAudioState object
final CallAudioState initState = new CallAudioState(false,
- mParams.initialRoute, (mParams.availableRoutes | CallAudioState.ROUTE_SPEAKER));
+ mParams.initialRoute, (mParams.availableRoutes | CallAudioState.ROUTE_SPEAKER),
+ mParams.initialBluetoothDevice, mParams.availableBluetoothDevices);
stateMachine.initialize(initState);
// Make the state machine have focus so that we actually do something
@@ -240,7 +267,8 @@
// Reset mocks to discard stuff from initialization
resetMocks();
setupMocksForParams(stateMachine, mParams);
- stateMachine.sendMessageWithSessionInfo(mParams.action);
+
+ sendActionToStateMachine(stateMachine);
waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
@@ -290,7 +318,8 @@
// Verify the end state
CallAudioState expectedState = new CallAudioState(false, mParams.expectedRoute,
- mParams.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER);
+ mParams.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER,
+ mParams.expectedBluetoothDevice, mParams.availableBluetoothDevices);
verifyNewSystemCallAudioState(initState, expectedState);
}
@@ -311,21 +340,23 @@
when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(
(mParams.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0
|| (mParams.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0);
+ when(mockBluetoothRouteManager.getConnectedDevices())
+ .thenReturn(mParams.availableBluetoothDevices);
when(mockAudioManager.isSpeakerphoneOn()).thenReturn(
mParams.initialRoute == CallAudioState.ROUTE_SPEAKER);
when(fakeCall.getSupportedAudioRoutes()).thenReturn(mParams.callSupportedRoutes);
// Set the initial CallAudioState object
CallAudioState initState = new CallAudioState(false,
- mParams.initialRoute, (mParams.availableRoutes | CallAudioState.ROUTE_SPEAKER));
+ mParams.initialRoute, (mParams.availableRoutes | CallAudioState.ROUTE_SPEAKER),
+ mParams.initialBluetoothDevice, mParams.availableBluetoothDevices);
stateMachine.initialize(initState);
// Omit the focus-getting statement
- stateMachine.sendMessageWithSessionInfo(mParams.action);
+ sendActionToStateMachine(stateMachine);
waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
+ waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
- Handler h = stateMachine.getHandler();
- waitForHandlerAction(h, TEST_TIMEOUT);
stateMachine.quitStateMachine();
// Verify that no substantive interactions have taken place with the
@@ -334,13 +365,15 @@
// Verify the end state
CallAudioState expectedState = new CallAudioState(false, mParams.expectedRoute,
- mParams.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER);
+ mParams.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER,
+ mParams.expectedBluetoothDevice, mParams.availableBluetoothDevices);
assertEquals(expectedState, stateMachine.getCurrentCallAudioState());
}
@Parameterized.Parameters(name = "{0}")
public static Collection<RoutingTestParameters> testParametersCollection() {
List<RoutingTestParameters> params = new ArrayList<>();
+
params.add(new RoutingTestParameters(
"Connect headset during earpiece", // name
CallAudioState.ROUTE_EARPIECE, // initialRoute
@@ -443,11 +476,11 @@
CallAudioState.ROUTE_EARPIECE, // availableRoutes
OPTIONAL, // speakerInteraction
ON, // bluetoothInteraction
- CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action
+ SPECIAL_CONNECT_BT_ACTION, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_EARPIECE, // expectedAvailable
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
- ));
+ ).setAvailableBluetoothDevices(BluetoothRouteManagerTest.DEVICE1));
params.add(new RoutingTestParameters(
"Connect bluetooth during wired headset", // name
@@ -455,11 +488,11 @@
CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes
OPTIONAL, // speakerInteraction
ON, // bluetoothInteraction
- CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action
+ SPECIAL_CONNECT_BT_ACTION, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvai
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
- ));
+ ).setAvailableBluetoothDevices(BluetoothRouteManagerTest.DEVICE1));
params.add(new RoutingTestParameters(
"Connect bluetooth during speakerphone", // name
@@ -467,11 +500,11 @@
CallAudioState.ROUTE_EARPIECE, // availableRoutes
OFF, // speakerInteraction
ON, // bluetoothInteraction
- CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action
+ SPECIAL_CONNECT_BT_ACTION, // action
CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_EARPIECE, // expectedAvailable
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
- ));
+ ).setAvailableBluetoothDevices(BluetoothRouteManagerTest.DEVICE1));
params.add(new RoutingTestParameters(
"Disconnect bluetooth during bluetooth without headset in", // name
@@ -479,19 +512,7 @@
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
OPTIONAL, // speakerInteraction
OFF, // bluetoothInteraction
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
- CallAudioState.ROUTE_EARPIECE, // expectedRoute
- CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
- CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
- ));
-
- params.add(new RoutingTestParameters(
- "Disconnect bluetooth during bluetooth without headset in, priority mode ", // name
- CallAudioState.ROUTE_BLUETOOTH, // initialRoute
- CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
- OPTIONAL, // speakerInteraction
- OFF, // bluetoothInteraction
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
+ SPECIAL_DISCONNECT_BT_ACTION, // action
CallAudioState.ROUTE_EARPIECE, // expectedRoute
CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
@@ -503,7 +524,7 @@
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
OPTIONAL, // speakerInteraction
OFF, // bluetoothInteraction
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
+ SPECIAL_DISCONNECT_BT_ACTION, // action
CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
@@ -515,7 +536,7 @@
CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
OPTIONAL, // speakerInteraction
NONE, // bluetoothInteraction
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
+ SPECIAL_DISCONNECT_BT_ACTION, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
@@ -527,7 +548,7 @@
CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
OPTIONAL, // speakerInteraction
NONE, // bluetoothInteraction
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
+ SPECIAL_DISCONNECT_BT_ACTION, // action
CallAudioState.ROUTE_EARPIECE, // expectedRoute
CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
@@ -695,12 +716,36 @@
CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
ON, // speakerInteraction
OFF, // bluetoothInteraction
- CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
+ SPECIAL_DISCONNECT_BT_ACTION, // action
CallAudioState.ROUTE_SPEAKER, // expectedRoute
CallAudioState.ROUTE_SPEAKER, // expectedAvailableRoutes
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
).setCallSupportedRoutes(CallAudioState.ROUTE_ALL & ~CallAudioState.ROUTE_EARPIECE));
+ params.add(new RoutingTestParameters(
+ "Active device deselected during BT", // name
+ CallAudioState.ROUTE_BLUETOOTH, // initialRoute
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
+ OPTIONAL, // speakerInteraction
+ OFF, // bluetoothInteraction
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE, // action
+ CallAudioState.ROUTE_EARPIECE, // expectedRoute
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailabl
+ CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
+ ));
+
+ params.add(new RoutingTestParameters(
+ "Active device selected during earpiece", // name
+ CallAudioState.ROUTE_EARPIECE, // initialRoute
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
+ OPTIONAL, // speakerInteraction
+ ON, // bluetoothInteraction
+ CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT, // action
+ CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailabl
+ CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED // earpieceControl
+ ));
+
return params;
}
@@ -717,9 +762,9 @@
verify(mockConnectionServiceWrapper, timeout(TEST_TIMEOUT).atLeastOnce())
.onCallAudioStateChanged(same(fakeCall), newStateCaptor2.capture());
- assertTrue(oldStateCaptor.getAllValues().get(0).equals(expectedOldState));
- assertTrue(newStateCaptor1.getValue().equals(expectedNewState));
- assertTrue(newStateCaptor2.getValue().equals(expectedNewState));
+ assertEquals(expectedOldState, oldStateCaptor.getAllValues().get(0));
+ assertEquals(expectedNewState, newStateCaptor1.getValue());
+ assertEquals(expectedNewState, newStateCaptor2.getValue());
}
private void verifyNoSystemAudioChanges() {