Loading android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +59 −6 Original line number Diff line number Diff line Loading @@ -114,7 +114,8 @@ class ActiveDeviceManager { private static final int MESSAGE_HFP_ACTION_CONNECTION_STATE_CHANGED = 4; private static final int MESSAGE_HFP_ACTION_ACTIVE_DEVICE_CHANGED = 5; private static final int MESSAGE_HEARING_AID_ACTION_ACTIVE_DEVICE_CHANGED = 6; private static final int MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED = 7; private static final int MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE_CHANGED = 8; private static final int MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED = 9; private final AdapterService mAdapterService; private final ServiceFactory mFactory; Loading @@ -125,6 +126,7 @@ class ActiveDeviceManager { private final List<BluetoothDevice> mA2dpConnectedDevices = new LinkedList<>(); private final List<BluetoothDevice> mHfpConnectedDevices = new LinkedList<>(); private final List<BluetoothDevice> mLeAudioConnectedDevices = new LinkedList<>(); private BluetoothDevice mA2dpActiveDevice = null; private BluetoothDevice mHfpActiveDevice = null; private BluetoothDevice mHearingAidActiveDevice = null; Loading Loading @@ -164,6 +166,10 @@ class ActiveDeviceManager { mHandler.obtainMessage(MESSAGE_HEARING_AID_ACTION_ACTIVE_DEVICE_CHANGED, intent).sendToTarget(); break; case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED: mHandler.obtainMessage(MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE_CHANGED, intent).sendToTarget(); break; case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED: mHandler.obtainMessage(MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED, intent).sendToTarget(); Loading Loading @@ -338,10 +344,56 @@ class ActiveDeviceManager { } break; case MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE_CHANGED: { Intent intent = (Intent) msg.obj; BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int prevState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1); int nextState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); if (prevState == nextState) { // Nothing has changed break; } if (nextState == BluetoothProfile.STATE_CONNECTED) { // Device connected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " connected"); } if (mLeAudioConnectedDevices.contains(device)) { break; // The device is already connected } mLeAudioConnectedDevices.add(device); if (mHearingAidActiveDevice == null) { // New connected device: select it as active setLeAudioActiveDevice(device); setA2dpActiveDevice(null); setHfpActiveDevice(null); } break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " disconnected"); } mLeAudioConnectedDevices.remove(device); if (mLeAudioConnectedDevices.isEmpty() && Objects.equals(mLeAudioActiveDevice, device)) { setLeAudioActiveDevice(null); } } } break; case MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED: { Intent intent = (Intent) msg.obj; BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device != null && !mLeAudioConnectedDevices.contains(device)) { mLeAudioConnectedDevices.add(device); } if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED): " + "device= " + device); Loading Loading @@ -423,6 +475,7 @@ class ActiveDeviceManager { filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED); mAdapterService.registerReceiver(mReceiver, filter); Loading android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +0 −4 Original line number Diff line number Diff line Loading @@ -1575,10 +1575,6 @@ public class LeAudioService extends ProfileService { LeAudioGroupDescriptor descriptor = getGroupDescriptor(myGroupId); if (descriptor != null) { descriptor.mIsConnected = true; /* HearingAid activates device after connection * A2dp makes active device via activedevicemanager - connection intent */ setActiveDevice(device); } else { Log.e(TAG, "no descriptors for group: " + myGroupId); } Loading android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +89 −0 Original line number Diff line number Diff line Loading @@ -332,6 +332,73 @@ public class ActiveDeviceManagerTest { Assert.assertEquals(null, mActiveDeviceManager.getHearingAidActiveDevice()); } /** * One LE Audio is connected. */ @Test public void onlyLeAudioConnected_setHeadsetActive() { leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); } /** * Two LE Audio are connected. Should set the second one active. */ @Test public void secondLeAudioConnected_setSecondLeAudioActive() { leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); leAudioConnected(mSecondaryAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice); } /** * One LE Audio is connected and disconnected later. Should then set active device to null. */ @Test public void lastLeAudioDisconnected_clearLeAudioActive() { leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); leAudioDisconnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(isNull()); } /** * Two LE Audio are connected and active device is explicitly set. */ @Test public void leAudioActiveDeviceSelected_setActive() { leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); leAudioConnected(mSecondaryAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice); leAudioActiveDeviceChanged(mLeAudioDevice); // Don't call mLeAudioService.setActiveDevice() TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper()); verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice); Assert.assertEquals(mLeAudioDevice, mActiveDeviceManager.getLeAudioActiveDevice()); } /** * Two LE Audio are connected and the current active is then disconnected. * Should then set active device to fallback device. */ @Test public void leAudioSecondDeviceDisconnected_fallbackDeviceActive() { leAudioConnected(mSecondaryAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice); leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); leAudioDisconnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice); } /** * A combo (A2DP + Headset) device is connected. Then an LE Audio is connected. */ Loading Loading @@ -492,6 +559,28 @@ public class ActiveDeviceManagerTest { mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } /** * Helper to indicate LE Audio connected for a device. */ private void leAudioConnected(BluetoothDevice device) { Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } /** * Helper to indicate LE Audio disconnected for a device. */ private void leAudioDisconnected(BluetoothDevice device) { Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTED); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } /** * Helper to indicate LE Audio active device changed for a device. */ Loading Loading
android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +59 −6 Original line number Diff line number Diff line Loading @@ -114,7 +114,8 @@ class ActiveDeviceManager { private static final int MESSAGE_HFP_ACTION_CONNECTION_STATE_CHANGED = 4; private static final int MESSAGE_HFP_ACTION_ACTIVE_DEVICE_CHANGED = 5; private static final int MESSAGE_HEARING_AID_ACTION_ACTIVE_DEVICE_CHANGED = 6; private static final int MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED = 7; private static final int MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE_CHANGED = 8; private static final int MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED = 9; private final AdapterService mAdapterService; private final ServiceFactory mFactory; Loading @@ -125,6 +126,7 @@ class ActiveDeviceManager { private final List<BluetoothDevice> mA2dpConnectedDevices = new LinkedList<>(); private final List<BluetoothDevice> mHfpConnectedDevices = new LinkedList<>(); private final List<BluetoothDevice> mLeAudioConnectedDevices = new LinkedList<>(); private BluetoothDevice mA2dpActiveDevice = null; private BluetoothDevice mHfpActiveDevice = null; private BluetoothDevice mHearingAidActiveDevice = null; Loading Loading @@ -164,6 +166,10 @@ class ActiveDeviceManager { mHandler.obtainMessage(MESSAGE_HEARING_AID_ACTION_ACTIVE_DEVICE_CHANGED, intent).sendToTarget(); break; case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED: mHandler.obtainMessage(MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE_CHANGED, intent).sendToTarget(); break; case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED: mHandler.obtainMessage(MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED, intent).sendToTarget(); Loading Loading @@ -338,10 +344,56 @@ class ActiveDeviceManager { } break; case MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE_CHANGED: { Intent intent = (Intent) msg.obj; BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int prevState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1); int nextState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); if (prevState == nextState) { // Nothing has changed break; } if (nextState == BluetoothProfile.STATE_CONNECTED) { // Device connected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " connected"); } if (mLeAudioConnectedDevices.contains(device)) { break; // The device is already connected } mLeAudioConnectedDevices.add(device); if (mHearingAidActiveDevice == null) { // New connected device: select it as active setLeAudioActiveDevice(device); setA2dpActiveDevice(null); setHfpActiveDevice(null); } break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " disconnected"); } mLeAudioConnectedDevices.remove(device); if (mLeAudioConnectedDevices.isEmpty() && Objects.equals(mLeAudioActiveDevice, device)) { setLeAudioActiveDevice(null); } } } break; case MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED: { Intent intent = (Intent) msg.obj; BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device != null && !mLeAudioConnectedDevices.contains(device)) { mLeAudioConnectedDevices.add(device); } if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED): " + "device= " + device); Loading Loading @@ -423,6 +475,7 @@ class ActiveDeviceManager { filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED); mAdapterService.registerReceiver(mReceiver, filter); Loading
android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +0 −4 Original line number Diff line number Diff line Loading @@ -1575,10 +1575,6 @@ public class LeAudioService extends ProfileService { LeAudioGroupDescriptor descriptor = getGroupDescriptor(myGroupId); if (descriptor != null) { descriptor.mIsConnected = true; /* HearingAid activates device after connection * A2dp makes active device via activedevicemanager - connection intent */ setActiveDevice(device); } else { Log.e(TAG, "no descriptors for group: " + myGroupId); } Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +89 −0 Original line number Diff line number Diff line Loading @@ -332,6 +332,73 @@ public class ActiveDeviceManagerTest { Assert.assertEquals(null, mActiveDeviceManager.getHearingAidActiveDevice()); } /** * One LE Audio is connected. */ @Test public void onlyLeAudioConnected_setHeadsetActive() { leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); } /** * Two LE Audio are connected. Should set the second one active. */ @Test public void secondLeAudioConnected_setSecondLeAudioActive() { leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); leAudioConnected(mSecondaryAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice); } /** * One LE Audio is connected and disconnected later. Should then set active device to null. */ @Test public void lastLeAudioDisconnected_clearLeAudioActive() { leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); leAudioDisconnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(isNull()); } /** * Two LE Audio are connected and active device is explicitly set. */ @Test public void leAudioActiveDeviceSelected_setActive() { leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); leAudioConnected(mSecondaryAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice); leAudioActiveDeviceChanged(mLeAudioDevice); // Don't call mLeAudioService.setActiveDevice() TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper()); verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice); Assert.assertEquals(mLeAudioDevice, mActiveDeviceManager.getLeAudioActiveDevice()); } /** * Two LE Audio are connected and the current active is then disconnected. * Should then set active device to fallback device. */ @Test public void leAudioSecondDeviceDisconnected_fallbackDeviceActive() { leAudioConnected(mSecondaryAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice); leAudioConnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice); leAudioDisconnected(mLeAudioDevice); verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice); } /** * A combo (A2DP + Headset) device is connected. Then an LE Audio is connected. */ Loading Loading @@ -492,6 +559,28 @@ public class ActiveDeviceManagerTest { mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } /** * Helper to indicate LE Audio connected for a device. */ private void leAudioConnected(BluetoothDevice device) { Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } /** * Helper to indicate LE Audio disconnected for a device. */ private void leAudioDisconnected(BluetoothDevice device) { Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTED); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } /** * Helper to indicate LE Audio active device changed for a device. */ Loading