Add support for Generic Telephone Bearer service (GTBS)

This patch integrates Telecomm service to GTBS

Bug: 150670922
Tag: #feature
Sponsor: jpawlowski@
Test: atest BluetoothInstrumentationTests TelecomUnitTests

Change-Id: I996cd5ff980a7a7e5fbfb05e18567264651f8935
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0776e9d..12481af 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -315,6 +315,9 @@
             <intent-filter>
                 <action android:name="android.bluetooth.IBluetoothHeadsetPhone"/>
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.bluetooth.IBluetoothLeCallControlCallback" />
+            </intent-filter>
         </service>
 
         <service android:name=".components.TelecomService"
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index e5a6ecc..f6f710e 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -875,8 +875,8 @@
                     return HANDLED;
                 case SWITCH_FOCUS:
                     if (msg.arg1 == NO_FOCUS) {
-                        // Only disconnect SCO audio here instead of routing away from BT entirely.
-                        mBluetoothRouteManager.disconnectSco();
+                        // Only disconnect audio here instead of routing away from BT entirely.
+                        mBluetoothRouteManager.disconnectAudio();
                         reinitialize();
                         mCallAudioManager.notifyAudioOperationsComplete();
                     } else if (msg.arg1 == RINGING_FOCUS
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index c7671e3..cb31990 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -20,6 +20,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.telecom.Log;
@@ -37,6 +38,11 @@
 import java.util.Set;
 
 public class BluetoothDeviceManager {
+
+    public static final int DEVICE_TYPE_HEADSET = 0;
+    public static final int DEVICE_TYPE_HEARING_AID = 1;
+    public static final int DEVICE_TYPE_LE_AUDIO = 2;
+
     private final BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
             new BluetoothProfile.ServiceListener() {
                 @Override
@@ -52,6 +58,10 @@
                                 mBluetoothHearingAid = (BluetoothHearingAid) proxy;
                                 logString = "Got BluetoothHearingAid: "
                                         + mBluetoothHearingAid;
+                            } else if (profile == BluetoothProfile.LE_AUDIO) {
+                                mBluetoothLeAudioService = (BluetoothLeAudio) proxy;
+                                logString = "Got BluetoothLeAudio: "
+                                        + mBluetoothLeAudioService;
                             } else {
                                 logString = "Connected to non-requested bluetooth service." +
                                         " Not changing bluetooth headset.";
@@ -74,7 +84,8 @@
                             if (profile == BluetoothProfile.HEADSET) {
                                 mBluetoothHeadset = null;
                                 lostServiceDevices = mHfpDevicesByAddress;
-                                mBluetoothRouteManager.onActiveDeviceChanged(null, false);
+                                mBluetoothRouteManager.onActiveDeviceChanged(null,
+                                        DEVICE_TYPE_HEADSET);
                                 logString = "Lost BluetoothHeadset service. " +
                                         "Removing all tracked devices";
                             } else if (profile == BluetoothProfile.HEARING_AID) {
@@ -82,7 +93,15 @@
                                 logString = "Lost BluetoothHearingAid service. " +
                                         "Removing all tracked devices.";
                                 lostServiceDevices = mHearingAidDevicesByAddress;
-                                mBluetoothRouteManager.onActiveDeviceChanged(null, true);
+                                mBluetoothRouteManager.onActiveDeviceChanged(null,
+                                        DEVICE_TYPE_HEARING_AID);
+                            } else if (profile == BluetoothProfile.LE_AUDIO) {
+                                mBluetoothLeAudioService = null;
+                                logString = "Lost BluetoothLeAudio service. " +
+                                        "Removing all tracked devices.";
+                                lostServiceDevices = mLeAudioDevicesByAddress;
+                                mBluetoothRouteManager.onActiveDeviceChanged(null,
+                                        DEVICE_TYPE_LE_AUDIO);
                             } else {
                                 return;
                             }
@@ -108,6 +127,12 @@
             new LinkedHashMap<>();
     private final LinkedHashMap<BluetoothDevice, Long> mHearingAidDeviceSyncIds =
             new LinkedHashMap<>();
+    private final LinkedHashMap<String, BluetoothDevice> mLeAudioDevicesByAddress =
+            new LinkedHashMap<>();
+    private final LinkedHashMap<BluetoothDevice, Integer> mGroupsByDevice =
+            new LinkedHashMap<>();
+    private int mGroupIdActive = BluetoothLeAudio.GROUP_ID_INVALID;
+    private int mGroupIdPending = BluetoothLeAudio.GROUP_ID_INVALID;
     private final LocalLog mLocalLog = new LocalLog(20);
 
     // This lock only protects internal state -- it doesn't lock on anything going into Telecom.
@@ -116,6 +141,7 @@
     private BluetoothRouteManager mBluetoothRouteManager;
     private BluetoothHeadset mBluetoothHeadset;
     private BluetoothHearingAid mBluetoothHearingAid;
+    private BluetoothLeAudio mBluetoothLeAudioService;
     private BluetoothDevice mBluetoothHearingAidActiveDeviceCache;
     private BluetoothAdapter mBluetoothAdapter;
 
@@ -126,6 +152,8 @@
                     BluetoothProfile.HEADSET);
             bluetoothAdapter.getProfileProxy(context, mBluetoothProfileServiceListener,
                     BluetoothProfile.HEARING_AID);
+            bluetoothAdapter.getProfileProxy(context, mBluetoothProfileServiceListener,
+                    BluetoothProfile.LE_AUDIO);
         }
     }
 
@@ -133,9 +161,20 @@
         mBluetoothRouteManager = brm;
     }
 
+    private List<BluetoothDevice> getLeAudioConnectedDevices() {
+        synchronized (mLock) {
+            // Filter out disconnected devices and/or those that have no group assigned
+            ArrayList<BluetoothDevice> devices = new ArrayList<>(mGroupsByDevice.keySet());
+            devices.removeIf(device -> !mLeAudioDevicesByAddress.containsValue(device));
+            return devices;
+        }
+    }
+
     public int getNumConnectedDevices() {
         synchronized (mLock) {
-            return mHfpDevicesByAddress.size() + mHearingAidDevicesByAddress.size();
+            return mHfpDevicesByAddress.size() +
+                    mHearingAidDevicesByAddress.size() +
+                    getLeAudioConnectedDevices().size();
         }
     }
 
@@ -143,6 +182,7 @@
         synchronized (mLock) {
             ArrayList<BluetoothDevice> result = new ArrayList<>(mHfpDevicesByAddress.values());
             result.addAll(mHearingAidDevicesByAddress.values());
+            result.addAll(getLeAudioConnectedDevices());
             return Collections.unmodifiableCollection(result);
         }
     }
@@ -177,6 +217,31 @@
                 seenHiSyncIds.add(hiSyncId);
             }
         }
+
+        Set<Integer> seenGroupIds = new LinkedHashSet<>();
+        if (mBluetoothAdapter != null) {
+            for (BluetoothDevice device : mBluetoothAdapter.getActiveDevices(
+                        BluetoothProfile.LE_AUDIO)) {
+                if (device != null) {
+                    result.add(device);
+                    seenGroupIds.add(mGroupsByDevice.getOrDefault(device, -1));
+                    break;
+                }
+            }
+        }
+        synchronized (mLock) {
+            for (BluetoothDevice d : getLeAudioConnectedDevices()) {
+                int groupId = mGroupsByDevice.getOrDefault(d,
+                        BluetoothLeAudio.GROUP_ID_INVALID);
+                if (groupId == BluetoothLeAudio.GROUP_ID_INVALID
+                        || seenGroupIds.contains(groupId)) {
+                    continue;
+                }
+                result.add(d);
+                seenGroupIds.add(groupId);
+            }
+        }
+
         return Collections.unmodifiableCollection(result);
     }
 
@@ -192,6 +257,10 @@
         return mBluetoothHearingAid;
     }
 
+    public BluetoothLeAudio getLeAudioService() {
+        return mBluetoothLeAudioService;
+    }
+
     public void setHeadsetServiceForTesting(BluetoothHeadset bluetoothHeadset) {
         mBluetoothHeadset = bluetoothHeadset;
     }
@@ -200,12 +269,33 @@
         mBluetoothHearingAid = bluetoothHearingAid;
     }
 
-    void onDeviceConnected(BluetoothDevice device, boolean isHearingAid) {
-        mLocalLog.log("Device connected -- address: " + device.getAddress() + " isHeadingAid: "
-                + isHearingAid);
+    public void setLeAudioServiceForTesting(BluetoothLeAudio bluetoothLeAudio) {
+        mBluetoothLeAudioService = bluetoothLeAudio;
+    }
+
+    public static String getDeviceTypeString(int deviceType) {
+        switch (deviceType) {
+            case DEVICE_TYPE_LE_AUDIO:
+                return "LeAudio";
+            case DEVICE_TYPE_HEARING_AID:
+                return "HearingAid";
+            case DEVICE_TYPE_HEADSET:
+                return "HFP";
+            default:
+                return "unknown type";
+        }
+    }
+
+    void onDeviceConnected(BluetoothDevice device, int deviceType) {
         synchronized (mLock) {
             LinkedHashMap<String, BluetoothDevice> targetDeviceMap;
-            if (isHearingAid) {
+            if (deviceType == DEVICE_TYPE_LE_AUDIO) {
+                if (mBluetoothLeAudioService == null) {
+                    Log.w(this, "LE audio service null when receiving device added broadcast");
+                    return;
+                }
+                targetDeviceMap = mLeAudioDevicesByAddress;
+            } else if (deviceType == DEVICE_TYPE_HEARING_AID) {
                 if (mBluetoothHearingAid == null) {
                     Log.w(this, "Hearing aid service null when receiving device added broadcast");
                     return;
@@ -213,12 +303,16 @@
                 long hiSyncId = mBluetoothHearingAid.getHiSyncId(device);
                 mHearingAidDeviceSyncIds.put(device, hiSyncId);
                 targetDeviceMap = mHearingAidDevicesByAddress;
-            } else {
+            } else if (deviceType == DEVICE_TYPE_HEADSET) {
                 if (mBluetoothHeadset == null) {
                     Log.w(this, "Headset service null when receiving device added broadcast");
                     return;
                 }
                 targetDeviceMap = mHfpDevicesByAddress;
+            } else {
+                Log.w(this, "Device: " + device.getAddress() + " with invalid type: "
+                            + getDeviceTypeString(deviceType));
+                return;
             }
             if (!targetDeviceMap.containsKey(device.getAddress())) {
                 targetDeviceMap.put(device.getAddress(), device);
@@ -227,16 +321,22 @@
         }
     }
 
-    void onDeviceDisconnected(BluetoothDevice device, boolean isHearingAid) {
-        mLocalLog.log("Device disconnected -- address: " + device.getAddress() + " isHeadingAid: "
-                + isHearingAid);
+    void onDeviceDisconnected(BluetoothDevice device, int deviceType) {
+        mLocalLog.log("Device disconnected -- address: " + device.getAddress() + " deviceType: "
+                + deviceType);
         synchronized (mLock) {
             LinkedHashMap<String, BluetoothDevice> targetDeviceMap;
-            if (isHearingAid) {
+            if (deviceType == DEVICE_TYPE_LE_AUDIO) {
+                targetDeviceMap = mLeAudioDevicesByAddress;
+            } else if (deviceType == DEVICE_TYPE_HEARING_AID) {
                 mHearingAidDeviceSyncIds.remove(device);
                 targetDeviceMap = mHearingAidDevicesByAddress;
-            } else {
+            } else if (deviceType == DEVICE_TYPE_HEADSET) {
                 targetDeviceMap = mHfpDevicesByAddress;
+            } else {
+                Log.w(this, "Device: " + device.getAddress() + " with invalid type: "
+                            + getDeviceTypeString(deviceType));
+                return;
             }
             if (targetDeviceMap.containsKey(device.getAddress())) {
                 targetDeviceMap.remove(device.getAddress());
@@ -245,16 +345,34 @@
         }
     }
 
+    void onGroupNodeAdded(BluetoothDevice device, int groupId) {
+        Log.i(this, device.getAddress() + " group added " + groupId);
+        if (device == null || groupId == BluetoothLeAudio.GROUP_ID_INVALID) {
+            Log.w(this, "invalid parameter");
+            return;
+        }
+
+        synchronized (mLock) {
+            mGroupsByDevice.put(device, groupId);
+        }
+    }
+
+    void onGroupNodeRemoved(BluetoothDevice device, int groupId) {
+        if (device == null || groupId == BluetoothLeAudio.GROUP_ID_INVALID) {
+            Log.w(this, "invalid parameter");
+            return;
+        }
+
+        synchronized (mLock) {
+            mGroupsByDevice.remove(device);
+        }
+    }
+
     public void disconnectAudio() {
         if (mBluetoothAdapter != null) {
-            for (BluetoothDevice device: mBluetoothAdapter.getActiveDevices(
-                        BluetoothProfile.HEARING_AID)) {
-                if (device != null) {
-                    mBluetoothAdapter.removeActiveDevice(BluetoothAdapter.ACTIVE_DEVICE_ALL);
-                }
-            }
+            mBluetoothAdapter.removeActiveDevice(BluetoothAdapter.ACTIVE_DEVICE_ALL);
+            disconnectSco();
         }
-        disconnectSco();
     }
 
     public void disconnectSco() {
@@ -265,10 +383,18 @@
         }
     }
 
-    // Connect audio to the bluetooth device at address, checking to see whether it's a hearing aid
-    // or a HFP device, and using the proper BT API.
+    // Connect audio to the bluetooth device at address, checking to see whether it's
+    // le audio, hearing aid or a HFP device, and using the proper BT API.
     public boolean connectAudio(String address) {
-        if (mHearingAidDevicesByAddress.containsKey(address)) {
+        if (mLeAudioDevicesByAddress.containsKey(address)) {
+            if (mBluetoothLeAudioService == null) {
+                Log.w(this, "Attempting to turn on audio when the le audio service is null");
+                return false;
+            }
+            BluetoothDevice device = mLeAudioDevicesByAddress.get(address);
+            return mBluetoothAdapter.setActiveDevice(
+                    device, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+        } else if (mHearingAidDevicesByAddress.containsKey(address)) {
             if (mBluetoothHearingAid == null) {
                 Log.w(this, "Attempting to turn on audio when the hearing aid service is null");
                 return false;
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
index 81f4ab6..163dbb2 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothLeAudio;
 import android.content.Context;
 import android.os.Message;
 import android.telecom.Log;
@@ -35,10 +36,12 @@
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
@@ -294,7 +297,7 @@
                         break;
                     case BT_AUDIO_IS_ON:
                         if (Objects.equals(mDeviceAddress, address)) {
-                            Log.i(LOG_TAG, "HFP connection success for device %s.", mDeviceAddress);
+                            Log.i(LOG_TAG, "BT connection success for device %s.", mDeviceAddress);
                             transitionTo(mAudioConnectedStates.get(mDeviceAddress));
                         } else {
                             Log.w(LOG_TAG, "In connecting state for device %s but %s" +
@@ -451,6 +454,7 @@
     // Tracks the active devices in the BT stack (HFP or hearing aid).
     private BluetoothDevice mHfpActiveDeviceCache = null;
     private BluetoothDevice mHearingAidActiveDeviceCache = null;
+    private BluetoothDevice mLeAudioDeviceCache = null;
     private BluetoothDevice mMostRecentlyReportedActiveDevice = null;
 
     public BluetoothRouteManager(Context context, TelecomSystem.SyncRoot lock,
@@ -548,8 +552,8 @@
         sendMessage(DISCONNECT_HFP, args);
     }
 
-    public void disconnectSco() {
-        mDeviceManager.disconnectSco();
+    public void disconnectAudio() {
+        mDeviceManager.disconnectAudio();
     }
 
     public void cacheHearingAidDevice() {
@@ -582,19 +586,37 @@
         mListener.onBluetoothDeviceListChanged();
     }
 
-    public void onActiveDeviceChanged(BluetoothDevice device, boolean isHearingAid) {
-        boolean wasActiveDevicePresent = mHearingAidActiveDeviceCache != null
-                || mHfpActiveDeviceCache != null;
-        if (isHearingAid) {
+    public void onAudioOn(String address) {
+        Session session = Log.createSubsession();
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = session;
+        args.arg2 = address;
+        sendMessage(BT_AUDIO_IS_ON, args);
+    }
+
+    public void onAudioLost(String address) {
+        Session session = Log.createSubsession();
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = session;
+        args.arg2 = address;
+        sendMessage(BT_AUDIO_LOST, args);
+    }
+
+    public void onActiveDeviceChanged(BluetoothDevice device, int deviceType) {
+        boolean wasActiveDevicePresent = hasBtActiveDevice();
+        if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO) {
+            mLeAudioDeviceCache = device;
+        } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID) {
             mHearingAidActiveDeviceCache = device;
-        } else {
+        } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEADSET) {
             mHfpActiveDeviceCache = device;
+        } else {
+            return;
         }
 
         if (device != null) mMostRecentlyReportedActiveDevice = device;
 
-        boolean isActiveDevicePresent = mHearingAidActiveDeviceCache != null
-                || mHfpActiveDeviceCache != null;
+        boolean isActiveDevicePresent = hasBtActiveDevice();
 
         if (wasActiveDevicePresent && !isActiveDevicePresent) {
             mListener.onBluetoothActiveDeviceGone();
@@ -604,7 +626,9 @@
     }
 
     public boolean hasBtActiveDevice() {
-        return mHearingAidActiveDeviceCache != null || mHfpActiveDeviceCache != null;
+        return mLeAudioDeviceCache != null ||
+                mHearingAidActiveDeviceCache != null ||
+                mHfpActiveDeviceCache != null;
     }
 
     public Collection<BluetoothDevice> getConnectedDevices() {
@@ -682,6 +706,9 @@
         if (mHearingAidActiveDeviceCache != null) {
             return mHearingAidActiveDeviceCache.getAddress();
         }
+        if (mLeAudioDeviceCache != null) {
+            return mLeAudioDeviceCache.getAddress();
+        }
         return null;
     }
 
@@ -705,29 +732,33 @@
         BluetoothAdapter bluetoothAdapter = mDeviceManager.getBluetoothAdapter();
         BluetoothHeadset bluetoothHeadset = mDeviceManager.getBluetoothHeadset();
         BluetoothHearingAid bluetoothHearingAid = mDeviceManager.getBluetoothHearingAid();
+        BluetoothLeAudio bluetoothLeAudio = mDeviceManager.getLeAudioService();
 
         BluetoothDevice hfpAudioOnDevice = null;
         BluetoothDevice hearingAidActiveDevice = null;
+        BluetoothDevice leAudioActiveDevice = null;
 
         if (bluetoothAdapter == null) {
             Log.i(this, "getBluetoothAudioConnectedDevice: no adapter available.");
             return null;
         }
-        if (bluetoothHeadset == null && bluetoothHearingAid == null) {
+        if (bluetoothHeadset == null && bluetoothHearingAid == null && bluetoothLeAudio == null) {
             Log.i(this, "getBluetoothAudioConnectedDevice: no service available.");
             return null;
         }
 
+        int activeDevices = 0;
         if (bluetoothHeadset != null) {
             for (BluetoothDevice device : bluetoothAdapter.getActiveDevices(
                         BluetoothProfile.HEADSET)) {
                 hfpAudioOnDevice = device;
                 break;
             }
-
             if (bluetoothHeadset.getAudioState(hfpAudioOnDevice)
                     == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
                 hfpAudioOnDevice = null;
+            } else {
+                activeDevices++;
             }
         }
 
@@ -736,22 +767,39 @@
                         BluetoothProfile.HEARING_AID)) {
                 if (device != null) {
                     hearingAidActiveDevice = device;
+                    activeDevices++;
                     break;
                 }
             }
         }
 
-        // Return the active device reported by either HFP or hearing aid. If both are reporting
-        // active devices, go with the most recent one as reported by the receiver.
-        if (hfpAudioOnDevice != null) {
-            if (hearingAidActiveDevice != null) {
-                Log.i(this, "Both HFP and hearing aid are reporting active devices. Going with"
-                        + " the most recently reported active device: %s");
-                return mMostRecentlyReportedActiveDevice;
+        if (bluetoothLeAudio != null) {
+            for (BluetoothDevice device : bluetoothLeAudio.getActiveDevices()) {
+                if (device != null) {
+                    leAudioActiveDevice = device;
+                    activeDevices++;
+                    break;
+                }
             }
-            return hfpAudioOnDevice;
         }
-        return hearingAidActiveDevice;
+
+        // Return the active device reported by either HFP, hearing aid or le audio. If more than
+        // one is reporting active devices, go with the most recent one as reported by the receiver.
+        if (activeDevices > 1) {
+            Log.i(this, "More than one profile reporting active devices. Going with the most"
+                    + " recently reported active device: %s", mMostRecentlyReportedActiveDevice);
+            return mMostRecentlyReportedActiveDevice;
+        }
+
+        if (leAudioActiveDevice != null) {
+            return leAudioActiveDevice;
+        }
+
+        if (hearingAidActiveDevice != null) {
+            return hearingAidActiveDevice;
+        }
+
+        return hfpAudioOnDevice;
     }
 
     /**
@@ -847,10 +895,12 @@
     }
 
     @VisibleForTesting
-    public void setActiveDeviceCacheForTesting(BluetoothDevice device, boolean isHearingAid) {
-        if (isHearingAid) {
+    public void setActiveDeviceCacheForTesting(BluetoothDevice device, int deviceType) {
+        if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO) {
+          mLeAudioDeviceCache = device;
+        } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID) {
             mHearingAidActiveDeviceCache = device;
-        } else {
+        } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEADSET) {
             mHfpActiveDeviceCache = device;
         }
     }
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index 8a14cbd..49489f4 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -19,6 +19,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -43,6 +44,10 @@
         INTENT_FILTER.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
         INTENT_FILTER.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
         INTENT_FILTER.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
+        INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
+        INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
+        INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED);
+        INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
     }
 
     // If not in a call, BSR won't listen to the Bluetooth stack's HFP on/off messages, since
@@ -59,14 +64,19 @@
                 case BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED:
                     handleAudioStateChanged(intent);
                     break;
+                case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
                 case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
                 case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
                     handleConnectionStateChanged(intent);
                     break;
+                case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
                 case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED:
                 case BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED:
                     handleActiveDeviceChanged(intent);
                     break;
+                case BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED:
+                    handleGroupNodeStatusChanged(intent);
+                    break;
             }
         } finally {
             Log.endSession();
@@ -117,29 +127,52 @@
             return;
         }
 
-        Log.i(LOG_TAG, "Device %s changed state to %d",
+        int deviceType;
+        if (BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
+            deviceType = BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO;
+        } else if (BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
+            deviceType = BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID;
+        } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
+            deviceType = BluetoothDeviceManager.DEVICE_TYPE_HEADSET;
+        } else {
+            Log.w(LOG_TAG, "handleConnectionStateChanged: %s invalid device type", device);
+            return;
+        }
+
+        Log.i(LOG_TAG, "%s device %s changed state to %d",
+                BluetoothDeviceManager.getDeviceTypeString(deviceType),
                 device.getAddress(), bluetoothHeadsetState);
 
-        boolean isHearingAid = BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED
-                .equals(intent.getAction());
         if (bluetoothHeadsetState == BluetoothProfile.STATE_CONNECTED) {
-            mBluetoothDeviceManager.onDeviceConnected(device, isHearingAid);
+            mBluetoothDeviceManager.onDeviceConnected(device, deviceType);
         } else if (bluetoothHeadsetState == BluetoothProfile.STATE_DISCONNECTED
                 || bluetoothHeadsetState == BluetoothProfile.STATE_DISCONNECTING) {
-            mBluetoothDeviceManager.onDeviceDisconnected(device, isHearingAid);
+            mBluetoothDeviceManager.onDeviceDisconnected(device, deviceType);
         }
     }
 
     private void handleActiveDeviceChanged(Intent intent) {
         BluetoothDevice device =
                 intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-        boolean isHearingAid =
-                BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED.equals(intent.getAction());
-        Log.i(LOG_TAG, "Device %s is now the preferred BT device for %s", device,
-                isHearingAid ? "hearing aid" : "HFP");
 
-        mBluetoothRouteManager.onActiveDeviceChanged(device, isHearingAid);
-        if (isHearingAid) {
+        int deviceType;
+        if (BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED.equals(intent.getAction())) {
+            deviceType = BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO;
+        } else if (BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED.equals(intent.getAction())) {
+            deviceType = BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID;
+        } else if (BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED.equals(intent.getAction())) {
+            deviceType = BluetoothDeviceManager.DEVICE_TYPE_HEADSET;
+        } else {
+            Log.w(LOG_TAG, "handleActiveDeviceChanged: %s invalid device type", device);
+            return;
+        }
+
+        Log.i(LOG_TAG, "Device %s is now the preferred BT device for %s", device,
+                BluetoothDeviceManager.getDeviceTypeString(deviceType));
+
+        mBluetoothRouteManager.onActiveDeviceChanged(device, deviceType);
+        if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID ||
+            deviceType == BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO) {
             Session session = Log.createSubsession();
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = session;
@@ -147,12 +180,28 @@
                 mBluetoothRouteManager.sendMessage(BT_AUDIO_LOST, args);
             } else {
                 if (!mIsInCall) {
-                    Log.i(LOG_TAG, "Ignoring hearing aid audio on since we're not in a call");
+                    Log.i(LOG_TAG, "Ignoring audio on since we're not in a call");
                     return;
                 }
                 args.arg2 = device.getAddress();
                 mBluetoothRouteManager.sendMessage(BT_AUDIO_IS_ON, args);
-            }
+           }
+        }
+    }
+
+    private void handleGroupNodeStatusChanged(Intent intent) {
+        BluetoothDevice device =
+                intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+        int groupId = intent.getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID,
+                BluetoothLeAudio.GROUP_ID_INVALID);
+        int groupNodeStatus = intent.getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_NODE_STATUS,
+                -1);
+
+        if (groupNodeStatus == BluetoothLeAudio.GROUP_NODE_ADDED) {
+            mBluetoothDeviceManager.onGroupNodeAdded(device, groupId);
+        } else {
+            mBluetoothDeviceManager.onGroupNodeRemoved(device, groupId);
         }
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index db26aaf..fe156dc 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -20,6 +20,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.Intent;
@@ -44,6 +45,7 @@
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -55,6 +57,7 @@
     @Mock BluetoothHeadset mBluetoothHeadset;
     @Mock BluetoothAdapter mAdapter;
     @Mock BluetoothHearingAid mBluetoothHearingAid;
+    @Mock BluetoothLeAudio mBluetoothLeAudio;
 
     BluetoothDeviceManager mBluetoothDeviceManager;
     BluetoothProfile.ServiceListener serviceListenerUnderTest;
@@ -64,6 +67,8 @@
     private BluetoothDevice device2;
     private BluetoothDevice device3;
     private BluetoothDevice device4;
+    private BluetoothDevice device5;
+    private BluetoothDevice device6;
 
     @Override
     @Before
@@ -75,6 +80,9 @@
         device3 = makeBluetoothDevice("00:00:00:00:00:03");
         // hearing aid
         device4 = makeBluetoothDevice("00:00:00:00:00:04");
+        // le audio
+        device5 = makeBluetoothDevice("00:00:00:00:00:05");
+        device6 = makeBluetoothDevice("00:00:00:00:00:06");
 
         when(mBluetoothHearingAid.getHiSyncId(device2)).thenReturn(100L);
         when(mBluetoothHearingAid.getHiSyncId(device4)).thenReturn(100L);
@@ -93,6 +101,7 @@
 
         mBluetoothDeviceManager.setHeadsetServiceForTesting(mBluetoothHeadset);
         mBluetoothDeviceManager.setHearingAidServiceForTesting(mBluetoothHearingAid);
+        mBluetoothDeviceManager.setLeAudioServiceForTesting(mBluetoothLeAudio);
     }
 
     @Override
@@ -105,10 +114,12 @@
     @Test
     public void testSingleDeviceConnectAndDisconnect() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices());
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         assertEquals(0, mBluetoothDeviceManager.getNumConnectedDevices());
     }
 
@@ -119,9 +130,14 @@
         mBluetoothDeviceManager.setHearingAidServiceForTesting(null);
 
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
 
         assertEquals(0, mBluetoothDeviceManager.getNumConnectedDevices());
     }
@@ -130,16 +146,37 @@
     @Test
     public void testMultiDeviceConnectAndDisconnect() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, false));
-        assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices());
+                buildGroupNodeStatusChangedIntent(1, device5, BluetoothLeAudio.GROUP_NODE_ADDED));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device3, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device6,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        receiverUnderTest.onReceive(mContext,
+                buildGroupNodeStatusChangedIntent(2, device6, BluetoothLeAudio.GROUP_NODE_ADDED));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        assertEquals(3, mBluetoothDeviceManager.getNumConnectedDevices());
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device3,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device6,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
         assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices());
     }
 
@@ -147,11 +184,34 @@
     @Test
     public void testHearingAidDedup() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device4, true));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device4,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
+        assertEquals(3, mBluetoothDeviceManager.getNumConnectedDevices());
+        assertEquals(2, mBluetoothDeviceManager.getUniqueConnectedDevices().size());
+    }
+
+    @SmallTest
+    @Test
+    public void testLeAudioDedup() {
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        receiverUnderTest.onReceive(mContext,
+                buildGroupNodeStatusChangedIntent(1, device5, BluetoothLeAudio.GROUP_NODE_ADDED));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device6,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        receiverUnderTest.onReceive(mContext,
+                buildGroupNodeStatusChangedIntent(1, device6, BluetoothLeAudio.GROUP_NODE_ADDED));
         assertEquals(3, mBluetoothDeviceManager.getNumConnectedDevices());
         assertEquals(2, mBluetoothDeviceManager.getUniqueConnectedDevices().size());
     }
@@ -160,14 +220,18 @@
     @Test
     public void testHeadsetServiceDisconnect() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
         serviceListenerUnderTest.onServiceDisconnected(BluetoothProfile.HEADSET);
 
-        verify(mRouteManager).onActiveDeviceChanged(isNull(), eq(false));
+        verify(mRouteManager).onActiveDeviceChanged(isNull(),
+                eq(BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         verify(mRouteManager).onDeviceLost(device1.getAddress());
         verify(mRouteManager).onDeviceLost(device3.getAddress());
         verify(mRouteManager, never()).onDeviceLost(device2.getAddress());
@@ -179,14 +243,18 @@
     @Test
     public void testHearingAidServiceDisconnect() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
         serviceListenerUnderTest.onServiceDisconnected(BluetoothProfile.HEARING_AID);
 
-        verify(mRouteManager).onActiveDeviceChanged(isNull(), eq(true));
+        verify(mRouteManager).onActiveDeviceChanged(isNull(),
+                eq(BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
         verify(mRouteManager).onDeviceLost(device2.getAddress());
         verify(mRouteManager, never()).onDeviceLost(device1.getAddress());
         verify(mRouteManager, never()).onDeviceLost(device3.getAddress());
@@ -196,16 +264,58 @@
 
     @SmallTest
     @Test
+    public void testLeAudioServiceDisconnect() {
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothLeAudio.STATE_CONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        serviceListenerUnderTest.onServiceDisconnected(BluetoothProfile.LE_AUDIO);
+
+        verify(mRouteManager).onActiveDeviceChanged(isNull(),
+                eq(BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        verify(mRouteManager).onDeviceLost(device5.getAddress());
+        verify(mRouteManager, never()).onDeviceLost(device1.getAddress());
+        verify(mRouteManager, never()).onDeviceLost(device3.getAddress());
+        assertNull(mBluetoothDeviceManager.getLeAudioService());
+        assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices());
+    }
+
+    @SmallTest
+    @Test
     public void testHearingAidChangesIgnoredWhenNotInCall() {
         receiverUnderTest.setIsInCall(false);
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
         Intent activeDeviceChangedIntent =
                 new Intent(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
         activeDeviceChangedIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device2);
         receiverUnderTest.onReceive(mContext, activeDeviceChangedIntent);
 
-        verify(mRouteManager).onActiveDeviceChanged(device2, true);
+        verify(mRouteManager).onActiveDeviceChanged(device2,
+                BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID);
+        verify(mRouteManager, never()).sendMessage(BluetoothRouteManager.BT_AUDIO_IS_ON);
+    }
+
+    @SmallTest
+    @Test
+    public void testLeAudioGroupChangesIgnoredWhenNotInCall() {
+        receiverUnderTest.setIsInCall(false);
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothLeAudio.STATE_CONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        Intent activeDeviceChangedIntent =
+                        new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
+        activeDeviceChangedIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device5);
+        receiverUnderTest.onReceive(mContext, activeDeviceChangedIntent);
+
+        verify(mRouteManager).onActiveDeviceChanged(device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO);
         verify(mRouteManager, never()).sendMessage(BluetoothRouteManager.BT_AUDIO_IS_ON);
     }
 
@@ -213,7 +323,8 @@
     @Test
     public void testConnectDisconnectAudioHeadset() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
                     eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
         mBluetoothDeviceManager.connectAudio(device1.getAddress());
@@ -228,7 +339,10 @@
     @Test
     public void testConnectDisconnectAudioHearingAid() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
+                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
+        when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
+                eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
         mBluetoothDeviceManager.connectAudio(device2.getAddress());
         verify(mAdapter).setActiveDevice(device2, BluetoothAdapter.ACTIVE_DEVICE_ALL);
         verify(mBluetoothHeadset, never()).connectAudio();
@@ -243,16 +357,98 @@
         verify(mBluetoothHeadset).disconnectAudio();
     }
 
-    private Intent buildConnectionActionIntent(int state, BluetoothDevice device,
-            boolean isHearingAid) {
-        Intent i = new Intent(isHearingAid
-                ? BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED
-                : BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
+    @SmallTest
+    @Test
+    public void testConnectDisconnectAudioLeAudio() {
+        receiverUnderTest.setIsInCall(true);
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        receiverUnderTest.onReceive(mContext,
+                buildGroupNodeStatusChangedIntent(1, device5, BluetoothLeAudio.GROUP_NODE_ADDED));
+        when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
+                eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
+        mBluetoothDeviceManager.connectAudio(device5.getAddress());
+        verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+        verify(mBluetoothHeadset, never()).connectAudio();
+        verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
+                eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL));
+
+        mBluetoothDeviceManager.disconnectAudio();
+        verify(mAdapter).removeActiveDevice(BluetoothAdapter.ACTIVE_DEVICE_ALL);
+    }
+
+    @SmallTest
+    @Test
+    public void testConnectEarbudLeAudio() {
+        receiverUnderTest.setIsInCall(true);
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        receiverUnderTest.onReceive(mContext,
+                buildGroupNodeStatusChangedIntent(1, device5, BluetoothLeAudio.GROUP_NODE_ADDED));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothLeAudio.STATE_CONNECTED, device6,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+        receiverUnderTest.onReceive(mContext,
+                buildGroupNodeStatusChangedIntent(1, device6, BluetoothLeAudio.GROUP_NODE_ADDED));
+        when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
+                eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
+        mBluetoothDeviceManager.connectAudio(device5.getAddress());
+        verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+        verify(mBluetoothHeadset, never()).connectAudio();
+        verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
+                eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL));
+
+        when(mBluetoothLeAudio.getActiveDevices()).thenReturn(Arrays.asList(device5, device6));
+
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device5,
+                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+
+        mBluetoothDeviceManager.connectAudio(device6.getAddress());
+        verify(mAdapter).setActiveDevice(device6, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+    }
+
+    private Intent buildConnectionActionIntent(int state, BluetoothDevice device, int deviceType) {
+        String intentString;
+
+        switch (deviceType) {
+            case BluetoothDeviceManager.DEVICE_TYPE_HEADSET:
+                intentString = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED;
+                break;
+            case BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID:
+                intentString = BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED;
+                break;
+            case BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO:
+                intentString = BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED;
+                break;
+            default:
+                return null;
+        }
+
+        Intent i = new Intent(intentString);
         i.putExtra(BluetoothHeadset.EXTRA_STATE, state);
         i.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
         return i;
     }
 
+    private Intent buildGroupNodeStatusChangedIntent(int groupId, BluetoothDevice device,
+                int nodeStatus) {
+        Intent i = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED);
+        i.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+        i.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, groupId);
+        i.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_NODE_STATUS, nodeStatus);
+        return i;
+    }
+
+    private Intent buildGroupStatusChangedIntent(int groupId, int groupStatus) {
+        Intent i = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
+        i.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, groupId);
+        i.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_STATUS, groupStatus);
+        return i;
+    }
+
     private BluetoothDevice makeBluetoothDevice(String address) {
         Parcel p1 = Parcel.obtain();
         p1.writeString(address);
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
index 28f6966..d6a6d11 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothLeAudio;
 import android.content.ContentResolver;
 import android.os.Parcel;
 import android.telecom.Log;
@@ -65,6 +66,7 @@
     @Mock private BluetoothDeviceManager mDeviceManager;
     @Mock private BluetoothHeadset mBluetoothHeadset;
     @Mock private BluetoothHearingAid mBluetoothHearingAid;
+    @Mock private BluetoothLeAudio mBluetoothLeAudio;
     @Mock private Timeouts.Adapter mTimeoutsAdapter;
     @Mock private BluetoothRouteManager.BluetoothStateListener mListener;
 
@@ -85,7 +87,7 @@
     public void testConnectHfpRetryWhileNotConnected() {
         BluetoothRouteManager sm = setupStateMachine(
                 BluetoothRouteManager.AUDIO_OFF_STATE_NAME, null);
-        setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null, null, null);
+        setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null, null, null, null, null);
         when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
                 nullable(ContentResolver.class))).thenReturn(0L);
         when(mBluetoothHeadset.connectAudio()).thenReturn(false);
@@ -108,13 +110,17 @@
         BluetoothRouteManager sm = setupStateMachine(
                 BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1);
         setupConnectedDevices(new BluetoothDevice[]{DEVICE1},
-                new BluetoothDevice[]{HEARING_AID_DEVICE}, DEVICE1, HEARING_AID_DEVICE);
-        sm.onActiveDeviceChanged(DEVICE1, false);
-        sm.onActiveDeviceChanged(HEARING_AID_DEVICE, true);
+                new BluetoothDevice[]{HEARING_AID_DEVICE}, new BluetoothDevice[]{DEVICE2},
+                DEVICE1, HEARING_AID_DEVICE, DEVICE2);
+        sm.onActiveDeviceChanged(DEVICE1, BluetoothDeviceManager.DEVICE_TYPE_HEADSET);
+        sm.onActiveDeviceChanged(DEVICE2, BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO);
+        sm.onActiveDeviceChanged(HEARING_AID_DEVICE,
+                BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID);
         executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, DEVICE1.getAddress());
 
         verifyConnectionAttempt(HEARING_AID_DEVICE, 0);
         verifyConnectionAttempt(DEVICE1, 0);
+        verifyConnectionAttempt(DEVICE2, 0);
         assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
                         + ":" + HEARING_AID_DEVICE.getAddress(),
                 sm.getCurrentState().getName());
@@ -126,7 +132,7 @@
     public void testAudioOnDeviceWithScoOffActiveDevice() {
         BluetoothRouteManager sm = setupStateMachine(
                 BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1);
-        setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null, DEVICE1, null);
+        setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null, null, DEVICE1, null, null);
         when(mBluetoothHeadset.getAudioState(DEVICE1))
                 .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
         executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, DEVICE1.getAddress());
@@ -142,7 +148,8 @@
     public void testConnectHfpRetryWhileConnectedToAnotherDevice() {
         BluetoothRouteManager sm = setupStateMachine(
                 BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1);
-        setupConnectedDevices(new BluetoothDevice[]{DEVICE1, DEVICE2}, null, null, null);
+        setupConnectedDevices(new BluetoothDevice[]{DEVICE1, DEVICE2}, null, null, null, null,
+                              null);
         when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
                 nullable(ContentResolver.class))).thenReturn(0L);
         when(mBluetoothHeadset.connectAudio()).thenReturn(false);
@@ -175,16 +182,18 @@
     }
 
     private void setupConnectedDevices(BluetoothDevice[] hfpDevices,
-            BluetoothDevice[] hearingAidDevices,
-            BluetoothDevice hfpActiveDevice, BluetoothDevice hearingAidActiveDevice) {
+            BluetoothDevice[] hearingAidDevices, BluetoothDevice[] leAudioDevices,
+            BluetoothDevice hfpActiveDevice, BluetoothDevice hearingAidActiveDevice,
+            BluetoothDevice leAudioDevice) {
         if (hfpDevices == null) hfpDevices = new BluetoothDevice[]{};
         if (hearingAidDevices == null) hearingAidDevices = new BluetoothDevice[]{};
+        if (leAudioDevice == null) leAudioDevices = new BluetoothDevice[]{};
 
         when(mDeviceManager.getNumConnectedDevices()).thenReturn(
-                hfpDevices.length + hearingAidDevices.length);
-        List<BluetoothDevice> allDevices = Stream.concat(
-                Arrays.stream(hfpDevices), Arrays.stream(hearingAidDevices))
-                .collect(Collectors.toList());
+                hfpDevices.length + hearingAidDevices.length + leAudioDevices.length);
+        List<BluetoothDevice> allDevices = Stream.of(
+                Arrays.stream(hfpDevices), Arrays.stream(hearingAidDevices),
+                Arrays.stream(leAudioDevices)).flatMap(i -> i).collect(Collectors.toList());
 
         when(mDeviceManager.getConnectedDevices()).thenReturn(allDevices);
         when(mBluetoothHeadset.getConnectedDevices()).thenReturn(Arrays.asList(hfpDevices));
@@ -197,6 +206,8 @@
                 .thenReturn(Arrays.asList(hearingAidDevices));
         when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID)))
                 .thenReturn(Arrays.asList(hearingAidActiveDevice, null));
+        when(mBluetoothLeAudio.getActiveDevices())
+                .thenReturn(Arrays.asList(leAudioDevice, null));
     }
 
     static void executeRoutingAction(BluetoothRouteManager brm, int message, String
@@ -222,6 +233,7 @@
         when(mDeviceManager.getBluetoothHeadset()).thenReturn(mBluetoothHeadset);
         when(mDeviceManager.getBluetoothHearingAid()).thenReturn(mBluetoothHearingAid);
         when(mDeviceManager.getBluetoothAdapter()).thenReturn(mBluetoothAdapter);
+        when(mDeviceManager.getLeAudioService()).thenReturn(mBluetoothLeAudio);
         when(mBluetoothHeadset.connectAudio()).thenReturn(true);
         when(mBluetoothHeadset.setActiveDevice(nullable(BluetoothDevice.class))).thenReturn(true);
         when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
index d96b687..ef16eff 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothLeAudio;
 import android.content.ContentResolver;
 import android.telecom.Log;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -43,6 +44,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Stream;
+import java.util.stream.Collectors;
 
 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.DEVICE1;
 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.DEVICE2;
@@ -80,6 +83,7 @@
         // the active device as returned by BluetoothAdapter#getActiveDevices
         private BluetoothDevice activeDevice = null;
         private List<BluetoothDevice> hearingAidBtDevices = Collections.emptyList();
+        private List<BluetoothDevice> leAudioDevices = Collections.emptyList();
 
         public BluetoothRouteTestParametersBuilder setName(String name) {
             this.name = name;
@@ -154,6 +158,12 @@
             return this;
         }
 
+        public BluetoothRouteTestParametersBuilder setLeAudioDevices(
+                List<BluetoothDevice> leAudioDevices) {
+            this.leAudioDevices = leAudioDevices;
+            return this;
+        }
+
         public BluetoothRouteTestParameters build() {
             return new BluetoothRouteTestParameters(name,
                     initialBluetoothState,
@@ -167,7 +177,8 @@
                     messageDevice,
                     audioOnDevice,
                     activeDevice,
-                    hearingAidBtDevices);
+                    hearingAidBtDevices,
+                    leAudioDevices);
 
         }
     }
@@ -187,6 +198,7 @@
         // the active device as returned by BluetoothAdapter#getActiveDevices
         private BluetoothDevice activeDevice = null;
         private List<BluetoothDevice> hearingAidBtDevices;
+        private List<BluetoothDevice> leAudioDevices;
 
         public BluetoothRouteTestParameters(String name, String initialBluetoothState,
                 BluetoothDevice initialDevice, int messageType, ListenerUpdate[]
@@ -194,7 +206,7 @@
                 expectedConnectionDevice, String expectedFinalStateName,
                 BluetoothDevice[] connectedDevices, BluetoothDevice messageDevice,
                 BluetoothDevice audioOnDevice, BluetoothDevice activeDevice,
-                List<BluetoothDevice> hearingAidBtDevices) {
+                List<BluetoothDevice> hearingAidBtDevices, List<BluetoothDevice> leAudioDevices) {
             this.name = name;
             this.initialBluetoothState = initialBluetoothState;
             this.initialDevice = initialDevice;
@@ -208,6 +220,7 @@
             this.audioOnDevice = audioOnDevice;
             this.activeDevice = activeDevice;
             this.hearingAidBtDevices = hearingAidBtDevices;
+            this.leAudioDevices = leAudioDevices;
         }
 
         @Override
@@ -225,6 +238,7 @@
                     ", connectedDevices=" + Arrays.toString(connectedDevices) +
                     ", activeDevice='" + activeDevice + '\'' +
                     ", hearingAidBtDevices ='" + hearingAidBtDevices + '\'' +
+                    ", leAudioDevices ='" + leAudioDevices + '\'' +
                     '}';
         }
     }
@@ -240,6 +254,7 @@
     @Mock private BluetoothAdapter mBluetoothAdapter;
     @Mock private BluetoothHeadset mBluetoothHeadset;
     @Mock private BluetoothHearingAid mBluetoothHearingAid;
+    @Mock private BluetoothLeAudio mBluetoothLeAudio;
     @Mock private Timeouts.Adapter mTimeoutsAdapter;
     @Mock private BluetoothRouteManager.BluetoothStateListener mListener;
 
@@ -266,10 +281,16 @@
         BluetoothRouteManager sm = setupStateMachine(
                 mParams.initialBluetoothState, mParams.initialDevice);
 
+        int deviceType = BluetoothDeviceManager.DEVICE_TYPE_HEADSET;
+        if (mParams.hearingAidBtDevices.contains(mParams.messageDevice)) {
+            deviceType = BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID;
+        } else if (mParams.hearingAidBtDevices.contains(mParams.messageDevice)) {
+            deviceType = BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO;
+        }
+
         setupConnectedDevices(mParams.connectedDevices,
                 mParams.audioOnDevice, mParams.activeDevice);
-        sm.setActiveDeviceCacheForTesting(mParams.activeDevice,
-                mParams.hearingAidBtDevices.contains(mParams.messageDevice));
+        sm.setActiveDeviceCacheForTesting(mParams.activeDevice, deviceType);
         if (mParams.initialDevice != null) {
             doAnswer(invocation -> {
                 SomeArgs args = SomeArgs.obtain();
@@ -285,14 +306,16 @@
         // 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,
-                    mParams.hearingAidBtDevices.contains(mParams.messageDevice));
+            sm.onActiveDeviceChanged(mParams.messageDevice, deviceType);
         } else if (mParams.messageType == BluetoothRouteManager.LOST_DEVICE) {
-            sm.onActiveDeviceChanged(null,
-                    mParams.hearingAidBtDevices.contains(mParams.messageDevice));
+            sm.onActiveDeviceChanged(null, deviceType);
             if (mParams.hearingAidBtDevices.contains(mParams.messageDevice)) {
                 when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID)))
                     .thenReturn(Arrays.asList(null, null));
+                when(mBluetoothLeAudio.getActiveDevices())
+                    .thenReturn(mParams.leAudioDevices.stream()
+                       .filter(device -> device != mParams.messageDevice)
+                       .collect(Collectors.toList()));
             } else {
                 when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEADSET)))
                     .thenReturn(Arrays.asList((BluetoothDevice) null));
@@ -368,6 +391,7 @@
         resetMocks();
         when(mDeviceManager.getBluetoothHeadset()).thenReturn(mBluetoothHeadset);
         when(mDeviceManager.getBluetoothHearingAid()).thenReturn(mBluetoothHearingAid);
+        when(mDeviceManager.getLeAudioService()).thenReturn(mBluetoothLeAudio);
         when(mDeviceManager.connectAudio(nullable(String.class))).thenReturn(true);
         when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
                 nullable(ContentResolver.class))).thenReturn(100000L);
@@ -660,6 +684,36 @@
                         + ":" + DEVICE2)
                 .build());
 
+        result.add(new BluetoothRouteTestParametersBuilder()
+                .setName("le audio device disconnects with hearing aid present")
+                .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
+                .setInitialDevice(DEVICE2)
+                .setConnectedDevices(DEVICE2, DEVICE3)
+                .setLeAudioDevices(Collections.singletonList(DEVICE2))
+                .setHearingAidBtDevices(Collections.singletonList(DEVICE3))
+                .setMessageType(BluetoothRouteManager.LOST_DEVICE)
+                .setMessageDevice(DEVICE2)
+                .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED,
+                        ListenerUpdate.DEVICE_LIST_CHANGED)
+                .setExpectedBluetoothInteraction(NONE)
+                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
+                .build());
+
+        result.add(new BluetoothRouteTestParametersBuilder()
+                .setName("le audio device disconnects with another one connected")
+                .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
+                .setInitialDevice(DEVICE1)
+                .setConnectedDevices(DEVICE1, DEVICE2, DEVICE3)
+                .setHearingAidBtDevices(Collections.singletonList(DEVICE3))
+                .setLeAudioDevices(Arrays.asList(DEVICE1, DEVICE2))
+                .setMessageType(BluetoothRouteManager.LOST_DEVICE)
+                .setMessageDevice(DEVICE1)
+                .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED,
+                        ListenerUpdate.DEVICE_LIST_CHANGED)
+                .setExpectedBluetoothInteraction(NONE)
+                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
+                .build());
+
         return result;
     }
 }