Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +4 −1 Original line number Diff line number Diff line Loading @@ -318,7 +318,10 @@ public class CachedBluetoothDeviceManager { return mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice, state); } if (profileId == BluetoothProfile.CSIP_SET_COORDINATOR) { if (profileId == BluetoothProfile.HEADSET || profileId == BluetoothProfile.A2DP || profileId == BluetoothProfile.LE_AUDIO || profileId == BluetoothProfile.CSIP_SET_COORDINATOR) { return mCsipDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice, state); } Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java +144 −142 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import androidx.annotation.ChecksSdkIntAtLeast; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; Loading Loading @@ -83,14 +84,14 @@ public class CsipDeviceManager { boolean setMemberDeviceIfNeeded(CachedBluetoothDevice newDevice) { final int groupId = newDevice.getGroupId(); if (isValidGroupId(groupId)) { final CachedBluetoothDevice CsipDevice = getCachedDevice(groupId); log("setMemberDeviceIfNeeded, main: " + CsipDevice + ", member: " + newDevice); final CachedBluetoothDevice mainDevice = getCachedDevice(groupId); log("setMemberDeviceIfNeeded, main: " + mainDevice + ", member: " + newDevice); // Just add one of the coordinated set from a pair in the list that is shown in the UI. // Once there is other devices with the same groupId, to add new device as member // devices. if (CsipDevice != null) { CsipDevice.addMemberDevice(newDevice); newDevice.setName(CsipDevice.getName()); if (mainDevice != null) { mainDevice.addMemberDevice(newDevice); newDevice.setName(mainDevice.getName()); return true; } } Loading Loading @@ -152,14 +153,7 @@ public class CsipDeviceManager { log("onGroupIdChanged: groupId is invalid"); return; } log("onGroupIdChanged: mCachedDevices list =" + mCachedDevices.toString()); List<CachedBluetoothDevice> memberDevicesList = getMemberDevicesList(groupId); CachedBluetoothDevice newMainDevice = getPreferredMainDeviceWithoutConectionState(groupId, memberDevicesList); log("onGroupIdChanged: The mainDevice= " + newMainDevice + " and the memberDevicesList of groupId= " + groupId + " =" + memberDevicesList); addMemberDevicesIntoMainDevice(memberDevicesList, newMainDevice); updateRelationshipOfGroupDevices(groupId); } // @return {@code true}, the event is processed inside the method. It is for updating Loading @@ -168,62 +162,31 @@ public class CsipDeviceManager { boolean onProfileConnectionStateChangedIfProcessed(CachedBluetoothDevice cachedDevice, int state) { log("onProfileConnectionStateChangedIfProcessed: " + cachedDevice + ", state: " + state); switch (state) { case BluetoothProfile.STATE_CONNECTED: onGroupIdChanged(cachedDevice.getGroupId()); CachedBluetoothDevice mainDevice = findMainDevice(cachedDevice); if (mainDevice != null) { if (mainDevice.isConnected()) { // When main device exists and in connected state, receiving member device // connection. To refresh main device UI mainDevice.refresh(); return true; } else { // When both LE Audio devices are disconnected, receiving member device // connection. To switch content and dispatch to notify UI change mBtManager.getEventManager().dispatchDeviceRemoved(mainDevice); mainDevice.switchMemberDeviceContent(cachedDevice); mainDevice.refresh(); // It is necessary to do remove and add for updating the mapping on // preference and device mBtManager.getEventManager().dispatchDeviceAdded(mainDevice); return true; } } break; case BluetoothProfile.STATE_DISCONNECTED: mainDevice = findMainDevice(cachedDevice); if (mainDevice != null) { // When main device exists, receiving sub device disconnection // To update main device UI mainDevice.refresh(); return true; } final Set<CachedBluetoothDevice> memberSet = cachedDevice.getMemberDevice(); if (memberSet.isEmpty()) { break; } for (CachedBluetoothDevice device : memberSet) { if (device.isConnected()) { log("set device: " + device + " as the main device"); // Main device is disconnected and sub device is connected // To copy data from sub device to main device mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice); cachedDevice.switchMemberDeviceContent(device); cachedDevice.refresh(); // It is necessary to do remove and add for updating the mapping on // preference and device mBtManager.getEventManager().dispatchDeviceAdded(cachedDevice); return true; } if (state != BluetoothProfile.STATE_CONNECTED && state != BluetoothProfile.STATE_DISCONNECTED) { return false; } break; default: // Do not handle this state. return updateRelationshipOfGroupDevices(cachedDevice.getGroupId()); } @VisibleForTesting boolean updateRelationshipOfGroupDevices(int groupId) { if (!isValidGroupId(groupId)) { log("The device is not group."); return false; } log("updateRelationshipOfGroupDevices: mCachedDevices list =" + mCachedDevices.toString()); // Get the preferred main device by getPreferredMainDeviceWithoutConectionState List<CachedBluetoothDevice> groupDevicesList = getGroupDevicesFromAllOfDevicesList(groupId); CachedBluetoothDevice preferredMainDevice = getPreferredMainDevice(groupId, groupDevicesList); log("The preferredMainDevice= " + preferredMainDevice + " and the groupDevicesList of groupId= " + groupId + " =" + groupDevicesList); return addMemberDevicesIntoMainDevice(groupId, preferredMainDevice); } CachedBluetoothDevice findMainDevice(CachedBluetoothDevice device) { if (device == null || mCachedDevices == null) { Loading Loading @@ -262,115 +225,154 @@ public class CsipDeviceManager { return false; } private List<CachedBluetoothDevice> getMemberDevicesList(int groupId) { return mCachedDevices.stream() .filter(cacheDevice -> cacheDevice.getGroupId() == groupId) .collect(Collectors.toList()); @VisibleForTesting List<CachedBluetoothDevice> getGroupDevicesFromAllOfDevicesList(int groupId) { List<CachedBluetoothDevice> groupDevicesList = new ArrayList<>(); if (!isValidGroupId(groupId)) { return groupDevicesList; } for (CachedBluetoothDevice item : mCachedDevices) { if (groupId != item.getGroupId()) { continue; } groupDevicesList.add(item); groupDevicesList.addAll(item.getMemberDevice()); } return groupDevicesList; } private CachedBluetoothDevice getPreferredMainDeviceWithoutConectionState(int groupId, List<CachedBluetoothDevice> memberDevicesList) { // First, priority connected lead device from LE profile // Second, the DUAL mode device which has A2DP/HFP and LE audio // Last, any one of LE device in the list. if (memberDevicesList == null || memberDevicesList.isEmpty()) { @VisibleForTesting CachedBluetoothDevice getPreferredMainDevice(int groupId, List<CachedBluetoothDevice> groupDevicesList) { // How to select the preferred main device? // 1. The DUAL mode connected device which has A2DP/HFP and LE audio. // 2. One of connected LE device in the list. Default is the lead device from LE profile. // 3. If there is no connected device, then reset the relationship. Set the DUAL mode // deviced as the main device. Otherwise, set any one of the device. if (groupDevicesList == null || groupDevicesList.isEmpty()) { return null; } CachedBluetoothDevice dualModeDevice = groupDevicesList.stream() .filter(cachedDevice -> cachedDevice.getConnectableProfiles().stream() .anyMatch(profile -> profile instanceof LeAudioProfile)) .filter(cachedDevice -> cachedDevice.getConnectableProfiles().stream() .anyMatch(profile -> profile instanceof A2dpProfile || profile instanceof HeadsetProfile)) .findFirst().orElse(null); if (dualModeDevice != null && dualModeDevice.isConnected()) { log("getPreferredMainDevice: The connected DUAL mode device"); return dualModeDevice; } final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager(); final LeAudioProfile leAudioProfile = profileManager.getLeAudioProfile(); final BluetoothDevice mainBluetoothDevice = (leAudioProfile != null && isAtLeastT()) final BluetoothDevice leAudioLeadDevice = (leAudioProfile != null && isAtLeastT()) ? leAudioProfile.getConnectedGroupLeadDevice(groupId) : null; if (mainBluetoothDevice != null) { if (leAudioLeadDevice != null) { log("getPreferredMainDevice: The LeadDevice from LE profile is " + mainBluetoothDevice.getAnonymizedAddress()); } // 1st CachedBluetoothDevice newMainDevice = mainBluetoothDevice != null ? deviceManager.findDevice(mainBluetoothDevice) : null; if (newMainDevice != null) { if (newMainDevice.isConnected()) { log("getPreferredMainDevice: The connected LeadDevice from LE profile"); return newMainDevice; } else { log("getPreferredMainDevice: The LeadDevice is not connect."); + leAudioLeadDevice.getAnonymizedAddress()); } } else { CachedBluetoothDevice leAudioLeadCachedDevice = leAudioLeadDevice != null ? deviceManager.findDevice(leAudioLeadDevice) : null; if (leAudioLeadCachedDevice == null) { log("getPreferredMainDevice: The LeadDevice is not in the all of devices list"); } else if (leAudioLeadCachedDevice.isConnected()) { log("getPreferredMainDevice: The connected LeadDevice from LE profile"); return leAudioLeadCachedDevice; } // 2nd newMainDevice = memberDevicesList.stream() .filter(cachedDevice -> cachedDevice.getConnectableProfiles().stream() .anyMatch(profile -> profile instanceof A2dpProfile || profile instanceof HeadsetProfile)) CachedBluetoothDevice oneOfConnectedDevices = groupDevicesList.stream() .filter(cachedDevice -> cachedDevice.isConnected()) .findFirst().orElse(null); if (newMainDevice != null) { log("getPreferredMainDevice: The DUAL mode device"); return newMainDevice; if (oneOfConnectedDevices != null) { log("getPreferredMainDevice: One of the connected devices."); return oneOfConnectedDevices; } if (dualModeDevice != null) { log("getPreferredMainDevice: The DUAL mode device."); return dualModeDevice; } // last if (!memberDevicesList.isEmpty()) { newMainDevice = memberDevicesList.get(0); if (!groupDevicesList.isEmpty()) { log("getPreferredMainDevice: One of the group devices."); return groupDevicesList.get(0); } return newMainDevice; return null; } private void addMemberDevicesIntoMainDevice(List<CachedBluetoothDevice> memberDevicesList, CachedBluetoothDevice newMainDevice) { if (newMainDevice == null) { @VisibleForTesting boolean addMemberDevicesIntoMainDevice(int groupId, CachedBluetoothDevice preferredMainDevice) { boolean hasChanged = false; if (preferredMainDevice == null) { log("addMemberDevicesIntoMainDevice: No main device. Do nothing."); return; } if (memberDevicesList.isEmpty()) { log("addMemberDevicesIntoMainDevice: No member device in list. Do nothing."); return; return hasChanged; } CachedBluetoothDevice mainDeviceOfNewMainDevice = findMainDevice(newMainDevice); boolean isMemberInOtherMainDevice = mainDeviceOfNewMainDevice != null; if (!memberDevicesList.contains(newMainDevice) && isMemberInOtherMainDevice) { log("addMemberDevicesIntoMainDevice: The 'new main device' is not in list, and it is " + "the member at other device. Do switch main and member."); // If the current main device is not preferred main device, then set it as new main device. // Otherwise, do nothing. BluetoothDevice bluetoothDeviceOfPreferredMainDevice = preferredMainDevice.getDevice(); CachedBluetoothDevice mainDeviceOfPreferredMainDevice = findMainDevice(preferredMainDevice); boolean hasPreferredMainDeviceAlreadyBeenMainDevice = mainDeviceOfPreferredMainDevice == null; if (!hasPreferredMainDeviceAlreadyBeenMainDevice) { // preferredMainDevice has not been the main device. // switch relationship between the mainDeviceOfPreferredMainDevice and // PreferredMainDevice log("addMemberDevicesIntoMainDevice: The PreferredMainDevice have the mainDevice. " + "Do switch relationship between the mainDeviceOfPreferredMainDevice and " + "PreferredMainDevice"); // To switch content and dispatch to notify UI change mBtManager.getEventManager().dispatchDeviceRemoved(mainDeviceOfNewMainDevice); mainDeviceOfNewMainDevice.switchMemberDeviceContent(newMainDevice); mainDeviceOfNewMainDevice.refresh(); mBtManager.getEventManager().dispatchDeviceRemoved(mainDeviceOfPreferredMainDevice); mainDeviceOfPreferredMainDevice.switchMemberDeviceContent(preferredMainDevice); mainDeviceOfPreferredMainDevice.refresh(); // It is necessary to do remove and add for updating the mapping on // preference and device mBtManager.getEventManager().dispatchDeviceAdded(mainDeviceOfNewMainDevice); } else { log("addMemberDevicesIntoMainDevice: Set new main device"); for (CachedBluetoothDevice memberDeviceItem : memberDevicesList) { if (memberDeviceItem.equals(newMainDevice)) { mBtManager.getEventManager().dispatchDeviceAdded(mainDeviceOfPreferredMainDevice); hasChanged = true; } // If the mCachedDevices List at CachedBluetoothDeviceManager has multiple items which are // the same groupId, then combine them and also keep the preferred main device as main // device. List<CachedBluetoothDevice> topLevelOfGroupDevicesList = mCachedDevices.stream() .filter(device -> device.getGroupId() == groupId) .collect(Collectors.toList()); boolean haveMultiMainDevicesInAllOfDevicesList = topLevelOfGroupDevicesList.size() > 1; // Update the new main of CachedBluetoothDevice, since it may be changed in above step. final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager(); preferredMainDevice = deviceManager.findDevice(bluetoothDeviceOfPreferredMainDevice); if (haveMultiMainDevicesInAllOfDevicesList) { // put another devices into main device. for (CachedBluetoothDevice deviceItem : topLevelOfGroupDevicesList) { if (deviceItem.getDevice() == null || deviceItem.getDevice().equals( bluetoothDeviceOfPreferredMainDevice)) { continue; } Set<CachedBluetoothDevice> memberSet = memberDeviceItem.getMemberDevice(); if (!memberSet.isEmpty()) { Set<CachedBluetoothDevice> memberSet = deviceItem.getMemberDevice(); for (CachedBluetoothDevice memberSetItem : memberSet) { if (!memberSetItem.equals(newMainDevice)) { newMainDevice.addMemberDevice(memberSetItem); if (!memberSetItem.equals(preferredMainDevice)) { preferredMainDevice.addMemberDevice(memberSetItem); } } memberSet.clear(); } newMainDevice.addMemberDevice(memberDeviceItem); mCachedDevices.remove(memberDeviceItem); mBtManager.getEventManager().dispatchDeviceRemoved(memberDeviceItem); } if (!mCachedDevices.contains(newMainDevice)) { mCachedDevices.add(newMainDevice); mBtManager.getEventManager().dispatchDeviceAdded(newMainDevice); preferredMainDevice.addMemberDevice(deviceItem); mCachedDevices.remove(deviceItem); mBtManager.getEventManager().dispatchDeviceRemoved(deviceItem); hasChanged = true; } } if (hasChanged) { log("addMemberDevicesIntoMainDevice: After changed, CachedBluetoothDevice list: " + mCachedDevices); } return hasChanged; } private void log(String msg) { if (DEBUG) { Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java 0 → 100644 +345 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +4 −1 Original line number Diff line number Diff line Loading @@ -318,7 +318,10 @@ public class CachedBluetoothDeviceManager { return mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice, state); } if (profileId == BluetoothProfile.CSIP_SET_COORDINATOR) { if (profileId == BluetoothProfile.HEADSET || profileId == BluetoothProfile.A2DP || profileId == BluetoothProfile.LE_AUDIO || profileId == BluetoothProfile.CSIP_SET_COORDINATOR) { return mCsipDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice, state); } Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java +144 −142 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import androidx.annotation.ChecksSdkIntAtLeast; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; Loading Loading @@ -83,14 +84,14 @@ public class CsipDeviceManager { boolean setMemberDeviceIfNeeded(CachedBluetoothDevice newDevice) { final int groupId = newDevice.getGroupId(); if (isValidGroupId(groupId)) { final CachedBluetoothDevice CsipDevice = getCachedDevice(groupId); log("setMemberDeviceIfNeeded, main: " + CsipDevice + ", member: " + newDevice); final CachedBluetoothDevice mainDevice = getCachedDevice(groupId); log("setMemberDeviceIfNeeded, main: " + mainDevice + ", member: " + newDevice); // Just add one of the coordinated set from a pair in the list that is shown in the UI. // Once there is other devices with the same groupId, to add new device as member // devices. if (CsipDevice != null) { CsipDevice.addMemberDevice(newDevice); newDevice.setName(CsipDevice.getName()); if (mainDevice != null) { mainDevice.addMemberDevice(newDevice); newDevice.setName(mainDevice.getName()); return true; } } Loading Loading @@ -152,14 +153,7 @@ public class CsipDeviceManager { log("onGroupIdChanged: groupId is invalid"); return; } log("onGroupIdChanged: mCachedDevices list =" + mCachedDevices.toString()); List<CachedBluetoothDevice> memberDevicesList = getMemberDevicesList(groupId); CachedBluetoothDevice newMainDevice = getPreferredMainDeviceWithoutConectionState(groupId, memberDevicesList); log("onGroupIdChanged: The mainDevice= " + newMainDevice + " and the memberDevicesList of groupId= " + groupId + " =" + memberDevicesList); addMemberDevicesIntoMainDevice(memberDevicesList, newMainDevice); updateRelationshipOfGroupDevices(groupId); } // @return {@code true}, the event is processed inside the method. It is for updating Loading @@ -168,62 +162,31 @@ public class CsipDeviceManager { boolean onProfileConnectionStateChangedIfProcessed(CachedBluetoothDevice cachedDevice, int state) { log("onProfileConnectionStateChangedIfProcessed: " + cachedDevice + ", state: " + state); switch (state) { case BluetoothProfile.STATE_CONNECTED: onGroupIdChanged(cachedDevice.getGroupId()); CachedBluetoothDevice mainDevice = findMainDevice(cachedDevice); if (mainDevice != null) { if (mainDevice.isConnected()) { // When main device exists and in connected state, receiving member device // connection. To refresh main device UI mainDevice.refresh(); return true; } else { // When both LE Audio devices are disconnected, receiving member device // connection. To switch content and dispatch to notify UI change mBtManager.getEventManager().dispatchDeviceRemoved(mainDevice); mainDevice.switchMemberDeviceContent(cachedDevice); mainDevice.refresh(); // It is necessary to do remove and add for updating the mapping on // preference and device mBtManager.getEventManager().dispatchDeviceAdded(mainDevice); return true; } } break; case BluetoothProfile.STATE_DISCONNECTED: mainDevice = findMainDevice(cachedDevice); if (mainDevice != null) { // When main device exists, receiving sub device disconnection // To update main device UI mainDevice.refresh(); return true; } final Set<CachedBluetoothDevice> memberSet = cachedDevice.getMemberDevice(); if (memberSet.isEmpty()) { break; } for (CachedBluetoothDevice device : memberSet) { if (device.isConnected()) { log("set device: " + device + " as the main device"); // Main device is disconnected and sub device is connected // To copy data from sub device to main device mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice); cachedDevice.switchMemberDeviceContent(device); cachedDevice.refresh(); // It is necessary to do remove and add for updating the mapping on // preference and device mBtManager.getEventManager().dispatchDeviceAdded(cachedDevice); return true; } if (state != BluetoothProfile.STATE_CONNECTED && state != BluetoothProfile.STATE_DISCONNECTED) { return false; } break; default: // Do not handle this state. return updateRelationshipOfGroupDevices(cachedDevice.getGroupId()); } @VisibleForTesting boolean updateRelationshipOfGroupDevices(int groupId) { if (!isValidGroupId(groupId)) { log("The device is not group."); return false; } log("updateRelationshipOfGroupDevices: mCachedDevices list =" + mCachedDevices.toString()); // Get the preferred main device by getPreferredMainDeviceWithoutConectionState List<CachedBluetoothDevice> groupDevicesList = getGroupDevicesFromAllOfDevicesList(groupId); CachedBluetoothDevice preferredMainDevice = getPreferredMainDevice(groupId, groupDevicesList); log("The preferredMainDevice= " + preferredMainDevice + " and the groupDevicesList of groupId= " + groupId + " =" + groupDevicesList); return addMemberDevicesIntoMainDevice(groupId, preferredMainDevice); } CachedBluetoothDevice findMainDevice(CachedBluetoothDevice device) { if (device == null || mCachedDevices == null) { Loading Loading @@ -262,115 +225,154 @@ public class CsipDeviceManager { return false; } private List<CachedBluetoothDevice> getMemberDevicesList(int groupId) { return mCachedDevices.stream() .filter(cacheDevice -> cacheDevice.getGroupId() == groupId) .collect(Collectors.toList()); @VisibleForTesting List<CachedBluetoothDevice> getGroupDevicesFromAllOfDevicesList(int groupId) { List<CachedBluetoothDevice> groupDevicesList = new ArrayList<>(); if (!isValidGroupId(groupId)) { return groupDevicesList; } for (CachedBluetoothDevice item : mCachedDevices) { if (groupId != item.getGroupId()) { continue; } groupDevicesList.add(item); groupDevicesList.addAll(item.getMemberDevice()); } return groupDevicesList; } private CachedBluetoothDevice getPreferredMainDeviceWithoutConectionState(int groupId, List<CachedBluetoothDevice> memberDevicesList) { // First, priority connected lead device from LE profile // Second, the DUAL mode device which has A2DP/HFP and LE audio // Last, any one of LE device in the list. if (memberDevicesList == null || memberDevicesList.isEmpty()) { @VisibleForTesting CachedBluetoothDevice getPreferredMainDevice(int groupId, List<CachedBluetoothDevice> groupDevicesList) { // How to select the preferred main device? // 1. The DUAL mode connected device which has A2DP/HFP and LE audio. // 2. One of connected LE device in the list. Default is the lead device from LE profile. // 3. If there is no connected device, then reset the relationship. Set the DUAL mode // deviced as the main device. Otherwise, set any one of the device. if (groupDevicesList == null || groupDevicesList.isEmpty()) { return null; } CachedBluetoothDevice dualModeDevice = groupDevicesList.stream() .filter(cachedDevice -> cachedDevice.getConnectableProfiles().stream() .anyMatch(profile -> profile instanceof LeAudioProfile)) .filter(cachedDevice -> cachedDevice.getConnectableProfiles().stream() .anyMatch(profile -> profile instanceof A2dpProfile || profile instanceof HeadsetProfile)) .findFirst().orElse(null); if (dualModeDevice != null && dualModeDevice.isConnected()) { log("getPreferredMainDevice: The connected DUAL mode device"); return dualModeDevice; } final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager(); final LeAudioProfile leAudioProfile = profileManager.getLeAudioProfile(); final BluetoothDevice mainBluetoothDevice = (leAudioProfile != null && isAtLeastT()) final BluetoothDevice leAudioLeadDevice = (leAudioProfile != null && isAtLeastT()) ? leAudioProfile.getConnectedGroupLeadDevice(groupId) : null; if (mainBluetoothDevice != null) { if (leAudioLeadDevice != null) { log("getPreferredMainDevice: The LeadDevice from LE profile is " + mainBluetoothDevice.getAnonymizedAddress()); } // 1st CachedBluetoothDevice newMainDevice = mainBluetoothDevice != null ? deviceManager.findDevice(mainBluetoothDevice) : null; if (newMainDevice != null) { if (newMainDevice.isConnected()) { log("getPreferredMainDevice: The connected LeadDevice from LE profile"); return newMainDevice; } else { log("getPreferredMainDevice: The LeadDevice is not connect."); + leAudioLeadDevice.getAnonymizedAddress()); } } else { CachedBluetoothDevice leAudioLeadCachedDevice = leAudioLeadDevice != null ? deviceManager.findDevice(leAudioLeadDevice) : null; if (leAudioLeadCachedDevice == null) { log("getPreferredMainDevice: The LeadDevice is not in the all of devices list"); } else if (leAudioLeadCachedDevice.isConnected()) { log("getPreferredMainDevice: The connected LeadDevice from LE profile"); return leAudioLeadCachedDevice; } // 2nd newMainDevice = memberDevicesList.stream() .filter(cachedDevice -> cachedDevice.getConnectableProfiles().stream() .anyMatch(profile -> profile instanceof A2dpProfile || profile instanceof HeadsetProfile)) CachedBluetoothDevice oneOfConnectedDevices = groupDevicesList.stream() .filter(cachedDevice -> cachedDevice.isConnected()) .findFirst().orElse(null); if (newMainDevice != null) { log("getPreferredMainDevice: The DUAL mode device"); return newMainDevice; if (oneOfConnectedDevices != null) { log("getPreferredMainDevice: One of the connected devices."); return oneOfConnectedDevices; } if (dualModeDevice != null) { log("getPreferredMainDevice: The DUAL mode device."); return dualModeDevice; } // last if (!memberDevicesList.isEmpty()) { newMainDevice = memberDevicesList.get(0); if (!groupDevicesList.isEmpty()) { log("getPreferredMainDevice: One of the group devices."); return groupDevicesList.get(0); } return newMainDevice; return null; } private void addMemberDevicesIntoMainDevice(List<CachedBluetoothDevice> memberDevicesList, CachedBluetoothDevice newMainDevice) { if (newMainDevice == null) { @VisibleForTesting boolean addMemberDevicesIntoMainDevice(int groupId, CachedBluetoothDevice preferredMainDevice) { boolean hasChanged = false; if (preferredMainDevice == null) { log("addMemberDevicesIntoMainDevice: No main device. Do nothing."); return; } if (memberDevicesList.isEmpty()) { log("addMemberDevicesIntoMainDevice: No member device in list. Do nothing."); return; return hasChanged; } CachedBluetoothDevice mainDeviceOfNewMainDevice = findMainDevice(newMainDevice); boolean isMemberInOtherMainDevice = mainDeviceOfNewMainDevice != null; if (!memberDevicesList.contains(newMainDevice) && isMemberInOtherMainDevice) { log("addMemberDevicesIntoMainDevice: The 'new main device' is not in list, and it is " + "the member at other device. Do switch main and member."); // If the current main device is not preferred main device, then set it as new main device. // Otherwise, do nothing. BluetoothDevice bluetoothDeviceOfPreferredMainDevice = preferredMainDevice.getDevice(); CachedBluetoothDevice mainDeviceOfPreferredMainDevice = findMainDevice(preferredMainDevice); boolean hasPreferredMainDeviceAlreadyBeenMainDevice = mainDeviceOfPreferredMainDevice == null; if (!hasPreferredMainDeviceAlreadyBeenMainDevice) { // preferredMainDevice has not been the main device. // switch relationship between the mainDeviceOfPreferredMainDevice and // PreferredMainDevice log("addMemberDevicesIntoMainDevice: The PreferredMainDevice have the mainDevice. " + "Do switch relationship between the mainDeviceOfPreferredMainDevice and " + "PreferredMainDevice"); // To switch content and dispatch to notify UI change mBtManager.getEventManager().dispatchDeviceRemoved(mainDeviceOfNewMainDevice); mainDeviceOfNewMainDevice.switchMemberDeviceContent(newMainDevice); mainDeviceOfNewMainDevice.refresh(); mBtManager.getEventManager().dispatchDeviceRemoved(mainDeviceOfPreferredMainDevice); mainDeviceOfPreferredMainDevice.switchMemberDeviceContent(preferredMainDevice); mainDeviceOfPreferredMainDevice.refresh(); // It is necessary to do remove and add for updating the mapping on // preference and device mBtManager.getEventManager().dispatchDeviceAdded(mainDeviceOfNewMainDevice); } else { log("addMemberDevicesIntoMainDevice: Set new main device"); for (CachedBluetoothDevice memberDeviceItem : memberDevicesList) { if (memberDeviceItem.equals(newMainDevice)) { mBtManager.getEventManager().dispatchDeviceAdded(mainDeviceOfPreferredMainDevice); hasChanged = true; } // If the mCachedDevices List at CachedBluetoothDeviceManager has multiple items which are // the same groupId, then combine them and also keep the preferred main device as main // device. List<CachedBluetoothDevice> topLevelOfGroupDevicesList = mCachedDevices.stream() .filter(device -> device.getGroupId() == groupId) .collect(Collectors.toList()); boolean haveMultiMainDevicesInAllOfDevicesList = topLevelOfGroupDevicesList.size() > 1; // Update the new main of CachedBluetoothDevice, since it may be changed in above step. final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager(); preferredMainDevice = deviceManager.findDevice(bluetoothDeviceOfPreferredMainDevice); if (haveMultiMainDevicesInAllOfDevicesList) { // put another devices into main device. for (CachedBluetoothDevice deviceItem : topLevelOfGroupDevicesList) { if (deviceItem.getDevice() == null || deviceItem.getDevice().equals( bluetoothDeviceOfPreferredMainDevice)) { continue; } Set<CachedBluetoothDevice> memberSet = memberDeviceItem.getMemberDevice(); if (!memberSet.isEmpty()) { Set<CachedBluetoothDevice> memberSet = deviceItem.getMemberDevice(); for (CachedBluetoothDevice memberSetItem : memberSet) { if (!memberSetItem.equals(newMainDevice)) { newMainDevice.addMemberDevice(memberSetItem); if (!memberSetItem.equals(preferredMainDevice)) { preferredMainDevice.addMemberDevice(memberSetItem); } } memberSet.clear(); } newMainDevice.addMemberDevice(memberDeviceItem); mCachedDevices.remove(memberDeviceItem); mBtManager.getEventManager().dispatchDeviceRemoved(memberDeviceItem); } if (!mCachedDevices.contains(newMainDevice)) { mCachedDevices.add(newMainDevice); mBtManager.getEventManager().dispatchDeviceAdded(newMainDevice); preferredMainDevice.addMemberDevice(deviceItem); mCachedDevices.remove(deviceItem); mBtManager.getEventManager().dispatchDeviceRemoved(deviceItem); hasChanged = true; } } if (hasChanged) { log("addMemberDevicesIntoMainDevice: After changed, CachedBluetoothDevice list: " + mCachedDevices); } return hasChanged; } private void log(String msg) { if (DEBUG) { Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java 0 → 100644 +345 −0 File added.Preview size limit exceeded, changes collapsed. Show changes