Merge "[LE Unicast] Using the active device as main device after grouping"
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index 89e10c4..fc70ba4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -20,15 +20,19 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
+import android.os.Build;
 import android.os.ParcelUuid;
 import android.util.Log;
 
+import androidx.annotation.ChecksSdkIntAtLeast;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * CsipDeviceManager manages the set of remote CSIP Bluetooth devices.
@@ -126,32 +130,84 @@
         }
     }
 
+    @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
+    private static boolean isAtLeastT() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
+    }
+
     // Group devices by groupId
     @VisibleForTesting
     void onGroupIdChanged(int groupId) {
-        int firstMatchedIndex = -1;
-        CachedBluetoothDevice mainDevice = null;
+        if (!isValidGroupId(groupId)) {
+            log("onGroupIdChanged: groupId is invalid");
+            return;
+        }
+        log("onGroupIdChanged: mCachedDevices list =" + mCachedDevices.toString());
+        final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+        final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager();
+        final LeAudioProfile leAudioProfile = profileManager.getLeAudioProfile();
+        final BluetoothDevice mainBluetoothDevice = (leAudioProfile != null && isAtLeastT()) ?
+                leAudioProfile.getConnectedGroupLeadDevice(groupId) : null;
+        CachedBluetoothDevice newMainDevice =
+                mainBluetoothDevice != null ? deviceManager.findDevice(mainBluetoothDevice) : null;
+        if (newMainDevice != null) {
+            final CachedBluetoothDevice finalNewMainDevice = newMainDevice;
+            final List<CachedBluetoothDevice> memberDevices = mCachedDevices.stream()
+                    .filter(cachedDevice -> !cachedDevice.equals(finalNewMainDevice)
+                            && cachedDevice.getGroupId() == groupId)
+                    .collect(Collectors.toList());
+            if (memberDevices == null || memberDevices.isEmpty()) {
+                log("onGroupIdChanged: There is no member device in list.");
+                return;
+            }
+            log("onGroupIdChanged: removed from UI device =" + memberDevices
+                    + ", with groupId=" + groupId + " mainDevice= " + newMainDevice);
+            for (CachedBluetoothDevice memberDeviceItem : memberDevices) {
+                Set<CachedBluetoothDevice> memberSet = memberDeviceItem.getMemberDevice();
+                if (!memberSet.isEmpty()) {
+                    log("onGroupIdChanged: Transfer the member list into new main device.");
+                    for (CachedBluetoothDevice memberListItem : memberSet) {
+                        if (!memberListItem.equals(newMainDevice)) {
+                            newMainDevice.addMemberDevice(memberListItem);
+                        }
+                    }
+                    memberSet.clear();
+                }
 
-        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
-            final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
-            if (cachedDevice.getGroupId() != groupId) {
-                continue;
+                newMainDevice.addMemberDevice(memberDeviceItem);
+                mCachedDevices.remove(memberDeviceItem);
+                mBtManager.getEventManager().dispatchDeviceRemoved(memberDeviceItem);
             }
 
-            if (firstMatchedIndex == -1) {
-                // Found the first one
-                firstMatchedIndex = i;
-                mainDevice = cachedDevice;
-                continue;
+            if (!mCachedDevices.contains(newMainDevice)) {
+                mCachedDevices.add(newMainDevice);
+                mBtManager.getEventManager().dispatchDeviceAdded(newMainDevice);
             }
+        } else {
+            log("onGroupIdChanged: There is no main device from the LE profile.");
+            int firstMatchedIndex = -1;
 
-            log("onGroupIdChanged: removed from UI device =" + cachedDevice
-                    + ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
+            for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+                final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+                if (cachedDevice.getGroupId() != groupId) {
+                    continue;
+                }
 
-            mainDevice.addMemberDevice(cachedDevice);
-            mCachedDevices.remove(i);
-            mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
-            break;
+                if (firstMatchedIndex == -1) {
+                    // Found the first one
+                    firstMatchedIndex = i;
+                    newMainDevice = cachedDevice;
+                    continue;
+                }
+
+                log("onGroupIdChanged: removed from UI device =" + cachedDevice
+                        + ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
+
+                newMainDevice.addMemberDevice(cachedDevice);
+                mCachedDevices.remove(i);
+                mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
+                break;
+            }
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
index c323c4e..b6dcdc3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -21,6 +21,7 @@
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
 
+import android.annotation.Nullable;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothCodecConfig;
@@ -183,6 +184,37 @@
         return mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
     }
 
+    /**
+     * Get Lead device for the group.
+     *
+     * Lead device is the device that can be used as an active device in the system.
+     * Active devices points to the Audio Device for the Le Audio group.
+     * This method returns the Lead devices for the connected LE Audio
+     * group and this device should be used in the setActiveDevice() method by other parts
+     * of the system, which wants to set to active a particular Le Audio group.
+     *
+     * Note: getActiveDevice() returns the Lead device for the currently active LE Audio group.
+     * Note: When Lead device gets disconnected while Le Audio group is active and has more devices
+     * in the group, then Lead device will not change. If Lead device gets disconnected, for the
+     * Le Audio group which is not active, a new Lead device will be chosen
+     *
+     * @param groupId The group id.
+     * @return group lead device.
+     *
+     * @hide
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    public @Nullable BluetoothDevice getConnectedGroupLeadDevice(int groupId) {
+        if (DEBUG) {
+            Log.d(TAG,"getConnectedGroupLeadDevice");
+        }
+        if (mService == null) {
+            Log.e(TAG,"No service.");
+            return null;
+        }
+        return mService.getConnectedGroupLeadDevice(groupId);
+    }
+
     @Override
     public boolean isEnabled(BluetoothDevice device) {
         if (mService == null || device == null) {