Loading android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +140 −37 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; /** Loading Loading @@ -143,7 +144,7 @@ public class LeAudioService extends ProfileService { private volatile BluetoothDevice mActiveBroadcastAudioDevice; private BluetoothDevice mExposedActiveDevice; private LeAudioCodecConfig mLeAudioCodecConfig; private final Object mGroupLock = new Object(); private final ReentrantLock mGroupLock = new ReentrantLock(); private FeatureFlags mFeatureFlags; ServiceFactory mServiceFactory = new ServiceFactory(); Loading Loading @@ -339,9 +340,12 @@ public class LeAudioService extends ProfileService { mBroadcastDescriptors.clear(); synchronized (mGroupLock) { mGroupLock.lock(); try { mDeviceDescriptors.clear(); mGroupDescriptors.clear(); } finally { mGroupLock.unlock(); } // Setup broadcast callbacks Loading Loading @@ -430,7 +434,8 @@ public class LeAudioService extends ProfileService { // Don't wait for async call with INACTIVE group status, clean active // device for active group. synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> entry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor descriptor = entry.getValue(); Integer group_id = entry.getKey(); Loading @@ -454,6 +459,8 @@ public class LeAudioService extends ProfileService { mDeviceDescriptors.clear(); mGroupDescriptors.clear(); } finally { mGroupLock.unlock(); } // Cleanup native interfaces Loading Loading @@ -607,7 +614,8 @@ public class LeAudioService extends ProfileService { return false; } synchronized (mGroupLock) { mGroupLock.lock(); try { boolean isInbandRingtoneEnabled = false; int groupId = getGroupId(device); if (groupId != LE_AUDIO_GROUP_ID_INVALID) { Loading @@ -624,6 +632,8 @@ public class LeAudioService extends ProfileService { return false; } sm.sendMessage(LeAudioStateMachine.CONNECT); } finally { mGroupLock.unlock(); } return true; Loading @@ -640,7 +650,8 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "disconnect(): " + device); } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { Log.e(TAG, "disconnect: No valid descriptor for device: " + device); Loading @@ -655,13 +666,16 @@ public class LeAudioService extends ProfileService { } sm.sendMessage(LeAudioStateMachine.DISCONNECT); } finally { mGroupLock.unlock(); } return true; } public List<BluetoothDevice> getConnectedDevices() { synchronized (mGroupLock) { mGroupLock.lock(); try { List<BluetoothDevice> devices = new ArrayList<>(); for (LeAudioDeviceDescriptor descriptor : mDeviceDescriptors.values()) { LeAudioStateMachine sm = descriptor.mStateMachine; Loading @@ -670,6 +684,8 @@ public class LeAudioService extends ProfileService { } } return devices; } finally { mGroupLock.unlock(); } } Loading @@ -690,7 +706,8 @@ public class LeAudioService extends ProfileService { if (bondedDevices == null) { return devices; } synchronized (mGroupLock) { mGroupLock.lock(); try { for (BluetoothDevice device : bondedDevices) { final ParcelUuid[] featureUuids = device.getUuids(); if (!Utils.arrayContains(featureUuids, BluetoothUuid.LE_AUDIO)) { Loading @@ -716,6 +733,8 @@ public class LeAudioService extends ProfileService { } } return devices; } finally { mGroupLock.unlock(); } } Loading @@ -727,13 +746,16 @@ public class LeAudioService extends ProfileService { @VisibleForTesting List<BluetoothDevice> getDevices() { List<BluetoothDevice> devices = new ArrayList<>(); synchronized (mGroupLock) { mGroupLock.lock(); try { for (LeAudioDeviceDescriptor descriptor : mDeviceDescriptors.values()) { if (descriptor.mStateMachine != null) { devices.add(descriptor.mStateMachine.getDevice()); } } return devices; } finally { mGroupLock.unlock(); } } Loading @@ -747,7 +769,8 @@ public class LeAudioService extends ProfileService { * {@link BluetoothProfile#STATE_DISCONNECTING} if this profile is being disconnected */ public int getConnectionState(BluetoothDevice device) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { return BluetoothProfile.STATE_DISCONNECTED; Loading @@ -758,6 +781,8 @@ public class LeAudioService extends ProfileService { return BluetoothProfile.STATE_DISCONNECTED; } return sm.getConnectionState(); } finally { mGroupLock.unlock(); } } Loading Loading @@ -795,8 +820,11 @@ public class LeAudioService extends ProfileService { * @return true given group exists, otherwise false */ public boolean isValidDeviceGroup(int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { return groupId != LE_AUDIO_GROUP_ID_INVALID && mGroupDescriptors.containsKey(groupId); } finally { mGroupLock.unlock(); } } Loading @@ -812,13 +840,16 @@ public class LeAudioService extends ProfileService { return result; } synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<BluetoothDevice, LeAudioDeviceDescriptor> entry : mDeviceDescriptors.entrySet()) { if (entry.getValue().mGroupId == groupId) { result.add(entry.getKey()); } } } finally { mGroupLock.unlock(); } return result; } Loading @@ -836,13 +867,16 @@ public class LeAudioService extends ProfileService { return result; } synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<BluetoothDevice, LeAudioDeviceDescriptor> entry : mDeviceDescriptors.entrySet()) { if (entry.getValue().mGroupId == groupId) { result.add(entry.getKey()); } } } finally { mGroupLock.unlock(); } return result; } Loading @@ -851,13 +885,16 @@ public class LeAudioService extends ProfileService { * Get the active device group id */ public Integer getActiveGroupId() { synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> entry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor descriptor = entry.getValue(); if (descriptor.mIsActive) { return entry.getKey(); } } } finally { mGroupLock.unlock(); } return LE_AUDIO_GROUP_ID_INVALID; } Loading Loading @@ -1177,13 +1214,16 @@ public class LeAudioService extends ProfileService { } private boolean areAllGroupsInNotActiveState() { synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> entry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor descriptor = entry.getValue(); if (descriptor.mIsActive) { return false; } } } finally { mGroupLock.unlock(); } return true; } Loading @@ -1192,7 +1232,8 @@ public class LeAudioService extends ProfileService { if (groupId == LE_AUDIO_GROUP_ID_INVALID) { return null; } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(groupId); if (groupDescriptor == null) { Log.e(TAG, "Group " + groupId + " does not exist"); Loading @@ -1217,6 +1258,8 @@ public class LeAudioService extends ProfileService { groupDescriptor.mCurrentLeadDevice = sm.getDevice(); return groupDescriptor.mCurrentLeadDevice; } } finally { mGroupLock.unlock(); } return null; } Loading Loading @@ -1447,7 +1490,8 @@ public class LeAudioService extends ProfileService { } boolean allLeAudioDevicesConnected() { synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<BluetoothDevice, LeAudioDeviceDescriptor> deviceEntry : mDeviceDescriptors.entrySet()) { LeAudioDeviceDescriptor deviceDescriptor = deviceEntry.getValue(); Loading @@ -1462,6 +1506,8 @@ public class LeAudioService extends ProfileService { return false; } } } finally { mGroupLock.unlock(); } return true; } Loading Loading @@ -1721,7 +1767,8 @@ public class LeAudioService extends ProfileService { } private void clearInactiveDueToContextTypeFlags() { synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> groupEntry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor groupDescriptor = groupEntry.getValue(); Loading @@ -1732,6 +1779,8 @@ public class LeAudioService extends ProfileService { groupDescriptor.mInactivatedDueToContextType = false; } } } finally { mGroupLock.unlock(); } } Loading Loading @@ -1948,7 +1997,8 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "connect(): " + storedDevice); } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioStateMachine sm = getOrCreateStateMachine(storedDevice); if (sm == null) { Log.e(TAG, "Ignored connect request for " + storedDevice Loading @@ -1956,6 +2006,8 @@ public class LeAudioService extends ProfileService { continue; } sm.sendMessage(LeAudioStateMachine.CONNECT); } finally { mGroupLock.unlock(); } } } Loading @@ -1975,7 +2027,8 @@ public class LeAudioService extends ProfileService { } private void clearLostDevicesWhileStreaming(LeAudioGroupDescriptor descriptor) { synchronized (mGroupLock) { mGroupLock.lock(); try { if (DBG) { Log.d(TAG, "Clearing lost dev: " + descriptor.mLostLeadDeviceWhileStreaming); } Loading @@ -1998,6 +2051,8 @@ public class LeAudioService extends ProfileService { sm.sendMessage(LeAudioStateMachine.STACK_EVENT, stackEvent); } descriptor.mLostLeadDeviceWhileStreaming = null; } finally { mGroupLock.unlock(); } } Loading Loading @@ -2074,7 +2129,8 @@ public class LeAudioService extends ProfileService { } private void handleGroupTransitToActive(int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId); if (descriptor == null || descriptor.mIsActive) { Log.e(TAG, "handleGroupTransitToActive: no descriptors for group: " + groupId Loading @@ -2089,11 +2145,14 @@ public class LeAudioService extends ProfileService { notifyGroupStatusChanged(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); updateInbandRingtoneForTheGroup(groupId); } } finally { mGroupLock.unlock(); } } private void handleGroupTransitToInactive(int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId); if (descriptor == null || !descriptor.mIsActive) { Log.e(TAG, "handleGroupTransitToInactive: no descriptors for group: " + groupId Loading Loading @@ -2127,6 +2186,8 @@ public class LeAudioService extends ProfileService { clearLostDevicesWhileStreaming(descriptor); notifyGroupStatusChanged(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); updateInbandRingtoneForTheGroup(groupId); } finally { mGroupLock.unlock(); } } Loading Loading @@ -2235,7 +2296,8 @@ public class LeAudioService extends ProfileService { return; } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(groupId); if (groupDescriptor == null) { Log.e(TAG, "group descriptor for " + groupId + " does not exist"); Loading Loading @@ -2293,6 +2355,8 @@ public class LeAudioService extends ProfileService { } } } } finally { mGroupLock.unlock(); } } Loading Loading @@ -2415,7 +2479,8 @@ public class LeAudioService extends ProfileService { if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { // Some events require device state machine synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(device); if (deviceDescriptor == null) { Log.e(TAG, "messageFromNative: No valid descriptor for device: " + device); Loading Loading @@ -2492,6 +2557,8 @@ public class LeAudioService extends ProfileService { sm.sendMessage(LeAudioStateMachine.STACK_EVENT, stackEvent); return; } finally { mGroupLock.unlock(); } } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_GROUP_NODE_STATUS_CHANGED) { int groupId = stackEvent.valueInt1; Loading Loading @@ -2561,7 +2628,8 @@ public class LeAudioService extends ProfileService { int src_audio_location = stackEvent.valueInt4; int available_contexts = stackEvent.valueInt5; synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId); if (descriptor != null) { if (descriptor.mIsActive) { Loading @@ -2588,6 +2656,8 @@ public class LeAudioService extends ProfileService { } else { Log.e(TAG, "messageFromNative: no descriptors for group: " + groupId); } } finally { mGroupLock.unlock(); } } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE) { Objects.requireNonNull(stackEvent.device, Loading Loading @@ -2885,7 +2955,8 @@ public class LeAudioService extends ProfileService { return; } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { Log.e(TAG, "bondStateChanged: No valid descriptor for device: " + device); Loading @@ -2912,11 +2983,14 @@ public class LeAudioService extends ProfileService { } removeStateMachine(device); removeAuthorizationInfoForRelatedProfiles(device); } finally { mGroupLock.unlock(); } } private void removeStateMachine(BluetoothDevice device) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { Log.e(TAG, "removeStateMachine: No valid descriptor for device: " + device); Loading @@ -2938,6 +3012,8 @@ public class LeAudioService extends ProfileService { if (!isScannerNeeded()) { stopAudioServersBackgroundScan(); } } finally { mGroupLock.unlock(); } } Loading Loading @@ -2987,7 +3063,8 @@ public class LeAudioService extends ProfileService { * Process a change for disconnection of a device. */ public synchronized void deviceDisconnected(BluetoothDevice device, boolean hasFallbackDevice) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(device); if (deviceDescriptor == null) { Log.e(TAG, "deviceDisconnected: No valid descriptor for device: " + device); Loading Loading @@ -3049,6 +3126,8 @@ public class LeAudioService extends ProfileService { hasFallbackDevice, false); } } finally { mGroupLock.unlock(); } } Loading Loading @@ -3298,7 +3377,8 @@ public class LeAudioService extends ProfileService { return LE_AUDIO_GROUP_ID_INVALID; } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { Log.e(TAG, "getGroupId: No valid descriptor for device: " + device); Loading @@ -3306,6 +3386,8 @@ public class LeAudioService extends ProfileService { } return descriptor.mGroupId; } finally { mGroupLock.unlock(); } } Loading Loading @@ -3411,37 +3493,50 @@ public class LeAudioService extends ProfileService { mBluetoothEnabled = true; synchronized (mGroupLock) { mGroupLock.lock(); try { if (mDeviceDescriptors.isEmpty()) { return; } } finally { mGroupLock.unlock(); } synchronized (mGroupLock) { mGroupLock.lock(); try { for (BluetoothDevice device : mDeviceDescriptors.keySet()) { if (getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { setAuthorizationForRelatedProfiles(device, true); } } } finally { mGroupLock.unlock(); } startAudioServersBackgroundScan(/* retry = */ false); } private LeAudioGroupDescriptor getGroupDescriptor(int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { return mGroupDescriptors.get(groupId); } finally { mGroupLock.unlock(); } } private LeAudioDeviceDescriptor getDeviceDescriptor(BluetoothDevice device) { synchronized (mGroupLock) { mGroupLock.lock(); try { return mDeviceDescriptors.get(device); } finally { mGroupLock.unlock(); } } private void handleGroupNodeAdded(BluetoothDevice device, int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { if (DBG) { Log.d(TAG, "Device " + device + " added to group " + groupId); } Loading Loading @@ -3475,6 +3570,8 @@ public class LeAudioService extends ProfileService { deviceDescriptor.mGroupId = groupId; notifyGroupNodeAdded(device, groupId); } finally { mGroupLock.unlock(); } if (mBluetoothEnabled) { Loading Loading @@ -3507,7 +3604,8 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "Removing device " + device + " grom group " + groupId); } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(groupId); if (groupDescriptor == null) { Log.e(TAG, "handleGroupNodeRemoved: No valid descriptor for group: " + groupId); Loading Loading @@ -3551,6 +3649,8 @@ public class LeAudioService extends ProfileService { } } notifyGroupNodeRemoved(device, groupId); } finally { mGroupLock.unlock(); } setAuthorizationForRelatedProfiles(device, false); Loading Loading @@ -4617,7 +4717,8 @@ public class LeAudioService extends ProfileService { + mLeAudioInbandRingtoneSupportedByPlatform); int numberOfUngroupedDevs = 0; synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> groupEntry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor groupDescriptor = groupEntry.getValue(); Loading Loading @@ -4661,6 +4762,8 @@ public class LeAudioService extends ProfileService { ProfileService.println(sb, " mDirection: " + deviceDescriptor.mDirection); } } } finally { mGroupLock.unlock(); } if (numberOfUngroupedDevs > 0) { Loading flags/leaudio.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -159,3 +159,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "leaudio_api_synchronized_block_fix" namespace: "bluetooth" description: "Fix possible deadlocks when synchronizing LeAudioService states" bug: "326295400" metadata { purpose: PURPOSE_BUGFIX } } Loading
android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +140 −37 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; /** Loading Loading @@ -143,7 +144,7 @@ public class LeAudioService extends ProfileService { private volatile BluetoothDevice mActiveBroadcastAudioDevice; private BluetoothDevice mExposedActiveDevice; private LeAudioCodecConfig mLeAudioCodecConfig; private final Object mGroupLock = new Object(); private final ReentrantLock mGroupLock = new ReentrantLock(); private FeatureFlags mFeatureFlags; ServiceFactory mServiceFactory = new ServiceFactory(); Loading Loading @@ -339,9 +340,12 @@ public class LeAudioService extends ProfileService { mBroadcastDescriptors.clear(); synchronized (mGroupLock) { mGroupLock.lock(); try { mDeviceDescriptors.clear(); mGroupDescriptors.clear(); } finally { mGroupLock.unlock(); } // Setup broadcast callbacks Loading Loading @@ -430,7 +434,8 @@ public class LeAudioService extends ProfileService { // Don't wait for async call with INACTIVE group status, clean active // device for active group. synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> entry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor descriptor = entry.getValue(); Integer group_id = entry.getKey(); Loading @@ -454,6 +459,8 @@ public class LeAudioService extends ProfileService { mDeviceDescriptors.clear(); mGroupDescriptors.clear(); } finally { mGroupLock.unlock(); } // Cleanup native interfaces Loading Loading @@ -607,7 +614,8 @@ public class LeAudioService extends ProfileService { return false; } synchronized (mGroupLock) { mGroupLock.lock(); try { boolean isInbandRingtoneEnabled = false; int groupId = getGroupId(device); if (groupId != LE_AUDIO_GROUP_ID_INVALID) { Loading @@ -624,6 +632,8 @@ public class LeAudioService extends ProfileService { return false; } sm.sendMessage(LeAudioStateMachine.CONNECT); } finally { mGroupLock.unlock(); } return true; Loading @@ -640,7 +650,8 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "disconnect(): " + device); } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { Log.e(TAG, "disconnect: No valid descriptor for device: " + device); Loading @@ -655,13 +666,16 @@ public class LeAudioService extends ProfileService { } sm.sendMessage(LeAudioStateMachine.DISCONNECT); } finally { mGroupLock.unlock(); } return true; } public List<BluetoothDevice> getConnectedDevices() { synchronized (mGroupLock) { mGroupLock.lock(); try { List<BluetoothDevice> devices = new ArrayList<>(); for (LeAudioDeviceDescriptor descriptor : mDeviceDescriptors.values()) { LeAudioStateMachine sm = descriptor.mStateMachine; Loading @@ -670,6 +684,8 @@ public class LeAudioService extends ProfileService { } } return devices; } finally { mGroupLock.unlock(); } } Loading @@ -690,7 +706,8 @@ public class LeAudioService extends ProfileService { if (bondedDevices == null) { return devices; } synchronized (mGroupLock) { mGroupLock.lock(); try { for (BluetoothDevice device : bondedDevices) { final ParcelUuid[] featureUuids = device.getUuids(); if (!Utils.arrayContains(featureUuids, BluetoothUuid.LE_AUDIO)) { Loading @@ -716,6 +733,8 @@ public class LeAudioService extends ProfileService { } } return devices; } finally { mGroupLock.unlock(); } } Loading @@ -727,13 +746,16 @@ public class LeAudioService extends ProfileService { @VisibleForTesting List<BluetoothDevice> getDevices() { List<BluetoothDevice> devices = new ArrayList<>(); synchronized (mGroupLock) { mGroupLock.lock(); try { for (LeAudioDeviceDescriptor descriptor : mDeviceDescriptors.values()) { if (descriptor.mStateMachine != null) { devices.add(descriptor.mStateMachine.getDevice()); } } return devices; } finally { mGroupLock.unlock(); } } Loading @@ -747,7 +769,8 @@ public class LeAudioService extends ProfileService { * {@link BluetoothProfile#STATE_DISCONNECTING} if this profile is being disconnected */ public int getConnectionState(BluetoothDevice device) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { return BluetoothProfile.STATE_DISCONNECTED; Loading @@ -758,6 +781,8 @@ public class LeAudioService extends ProfileService { return BluetoothProfile.STATE_DISCONNECTED; } return sm.getConnectionState(); } finally { mGroupLock.unlock(); } } Loading Loading @@ -795,8 +820,11 @@ public class LeAudioService extends ProfileService { * @return true given group exists, otherwise false */ public boolean isValidDeviceGroup(int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { return groupId != LE_AUDIO_GROUP_ID_INVALID && mGroupDescriptors.containsKey(groupId); } finally { mGroupLock.unlock(); } } Loading @@ -812,13 +840,16 @@ public class LeAudioService extends ProfileService { return result; } synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<BluetoothDevice, LeAudioDeviceDescriptor> entry : mDeviceDescriptors.entrySet()) { if (entry.getValue().mGroupId == groupId) { result.add(entry.getKey()); } } } finally { mGroupLock.unlock(); } return result; } Loading @@ -836,13 +867,16 @@ public class LeAudioService extends ProfileService { return result; } synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<BluetoothDevice, LeAudioDeviceDescriptor> entry : mDeviceDescriptors.entrySet()) { if (entry.getValue().mGroupId == groupId) { result.add(entry.getKey()); } } } finally { mGroupLock.unlock(); } return result; } Loading @@ -851,13 +885,16 @@ public class LeAudioService extends ProfileService { * Get the active device group id */ public Integer getActiveGroupId() { synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> entry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor descriptor = entry.getValue(); if (descriptor.mIsActive) { return entry.getKey(); } } } finally { mGroupLock.unlock(); } return LE_AUDIO_GROUP_ID_INVALID; } Loading Loading @@ -1177,13 +1214,16 @@ public class LeAudioService extends ProfileService { } private boolean areAllGroupsInNotActiveState() { synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> entry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor descriptor = entry.getValue(); if (descriptor.mIsActive) { return false; } } } finally { mGroupLock.unlock(); } return true; } Loading @@ -1192,7 +1232,8 @@ public class LeAudioService extends ProfileService { if (groupId == LE_AUDIO_GROUP_ID_INVALID) { return null; } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(groupId); if (groupDescriptor == null) { Log.e(TAG, "Group " + groupId + " does not exist"); Loading @@ -1217,6 +1258,8 @@ public class LeAudioService extends ProfileService { groupDescriptor.mCurrentLeadDevice = sm.getDevice(); return groupDescriptor.mCurrentLeadDevice; } } finally { mGroupLock.unlock(); } return null; } Loading Loading @@ -1447,7 +1490,8 @@ public class LeAudioService extends ProfileService { } boolean allLeAudioDevicesConnected() { synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<BluetoothDevice, LeAudioDeviceDescriptor> deviceEntry : mDeviceDescriptors.entrySet()) { LeAudioDeviceDescriptor deviceDescriptor = deviceEntry.getValue(); Loading @@ -1462,6 +1506,8 @@ public class LeAudioService extends ProfileService { return false; } } } finally { mGroupLock.unlock(); } return true; } Loading Loading @@ -1721,7 +1767,8 @@ public class LeAudioService extends ProfileService { } private void clearInactiveDueToContextTypeFlags() { synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> groupEntry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor groupDescriptor = groupEntry.getValue(); Loading @@ -1732,6 +1779,8 @@ public class LeAudioService extends ProfileService { groupDescriptor.mInactivatedDueToContextType = false; } } } finally { mGroupLock.unlock(); } } Loading Loading @@ -1948,7 +1997,8 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "connect(): " + storedDevice); } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioStateMachine sm = getOrCreateStateMachine(storedDevice); if (sm == null) { Log.e(TAG, "Ignored connect request for " + storedDevice Loading @@ -1956,6 +2006,8 @@ public class LeAudioService extends ProfileService { continue; } sm.sendMessage(LeAudioStateMachine.CONNECT); } finally { mGroupLock.unlock(); } } } Loading @@ -1975,7 +2027,8 @@ public class LeAudioService extends ProfileService { } private void clearLostDevicesWhileStreaming(LeAudioGroupDescriptor descriptor) { synchronized (mGroupLock) { mGroupLock.lock(); try { if (DBG) { Log.d(TAG, "Clearing lost dev: " + descriptor.mLostLeadDeviceWhileStreaming); } Loading @@ -1998,6 +2051,8 @@ public class LeAudioService extends ProfileService { sm.sendMessage(LeAudioStateMachine.STACK_EVENT, stackEvent); } descriptor.mLostLeadDeviceWhileStreaming = null; } finally { mGroupLock.unlock(); } } Loading Loading @@ -2074,7 +2129,8 @@ public class LeAudioService extends ProfileService { } private void handleGroupTransitToActive(int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId); if (descriptor == null || descriptor.mIsActive) { Log.e(TAG, "handleGroupTransitToActive: no descriptors for group: " + groupId Loading @@ -2089,11 +2145,14 @@ public class LeAudioService extends ProfileService { notifyGroupStatusChanged(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); updateInbandRingtoneForTheGroup(groupId); } } finally { mGroupLock.unlock(); } } private void handleGroupTransitToInactive(int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId); if (descriptor == null || !descriptor.mIsActive) { Log.e(TAG, "handleGroupTransitToInactive: no descriptors for group: " + groupId Loading Loading @@ -2127,6 +2186,8 @@ public class LeAudioService extends ProfileService { clearLostDevicesWhileStreaming(descriptor); notifyGroupStatusChanged(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); updateInbandRingtoneForTheGroup(groupId); } finally { mGroupLock.unlock(); } } Loading Loading @@ -2235,7 +2296,8 @@ public class LeAudioService extends ProfileService { return; } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(groupId); if (groupDescriptor == null) { Log.e(TAG, "group descriptor for " + groupId + " does not exist"); Loading Loading @@ -2293,6 +2355,8 @@ public class LeAudioService extends ProfileService { } } } } finally { mGroupLock.unlock(); } } Loading Loading @@ -2415,7 +2479,8 @@ public class LeAudioService extends ProfileService { if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { // Some events require device state machine synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(device); if (deviceDescriptor == null) { Log.e(TAG, "messageFromNative: No valid descriptor for device: " + device); Loading Loading @@ -2492,6 +2557,8 @@ public class LeAudioService extends ProfileService { sm.sendMessage(LeAudioStateMachine.STACK_EVENT, stackEvent); return; } finally { mGroupLock.unlock(); } } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_GROUP_NODE_STATUS_CHANGED) { int groupId = stackEvent.valueInt1; Loading Loading @@ -2561,7 +2628,8 @@ public class LeAudioService extends ProfileService { int src_audio_location = stackEvent.valueInt4; int available_contexts = stackEvent.valueInt5; synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId); if (descriptor != null) { if (descriptor.mIsActive) { Loading @@ -2588,6 +2656,8 @@ public class LeAudioService extends ProfileService { } else { Log.e(TAG, "messageFromNative: no descriptors for group: " + groupId); } } finally { mGroupLock.unlock(); } } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE) { Objects.requireNonNull(stackEvent.device, Loading Loading @@ -2885,7 +2955,8 @@ public class LeAudioService extends ProfileService { return; } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { Log.e(TAG, "bondStateChanged: No valid descriptor for device: " + device); Loading @@ -2912,11 +2983,14 @@ public class LeAudioService extends ProfileService { } removeStateMachine(device); removeAuthorizationInfoForRelatedProfiles(device); } finally { mGroupLock.unlock(); } } private void removeStateMachine(BluetoothDevice device) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { Log.e(TAG, "removeStateMachine: No valid descriptor for device: " + device); Loading @@ -2938,6 +3012,8 @@ public class LeAudioService extends ProfileService { if (!isScannerNeeded()) { stopAudioServersBackgroundScan(); } } finally { mGroupLock.unlock(); } } Loading Loading @@ -2987,7 +3063,8 @@ public class LeAudioService extends ProfileService { * Process a change for disconnection of a device. */ public synchronized void deviceDisconnected(BluetoothDevice device, boolean hasFallbackDevice) { synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(device); if (deviceDescriptor == null) { Log.e(TAG, "deviceDisconnected: No valid descriptor for device: " + device); Loading Loading @@ -3049,6 +3126,8 @@ public class LeAudioService extends ProfileService { hasFallbackDevice, false); } } finally { mGroupLock.unlock(); } } Loading Loading @@ -3298,7 +3377,8 @@ public class LeAudioService extends ProfileService { return LE_AUDIO_GROUP_ID_INVALID; } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device); if (descriptor == null) { Log.e(TAG, "getGroupId: No valid descriptor for device: " + device); Loading @@ -3306,6 +3386,8 @@ public class LeAudioService extends ProfileService { } return descriptor.mGroupId; } finally { mGroupLock.unlock(); } } Loading Loading @@ -3411,37 +3493,50 @@ public class LeAudioService extends ProfileService { mBluetoothEnabled = true; synchronized (mGroupLock) { mGroupLock.lock(); try { if (mDeviceDescriptors.isEmpty()) { return; } } finally { mGroupLock.unlock(); } synchronized (mGroupLock) { mGroupLock.lock(); try { for (BluetoothDevice device : mDeviceDescriptors.keySet()) { if (getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { setAuthorizationForRelatedProfiles(device, true); } } } finally { mGroupLock.unlock(); } startAudioServersBackgroundScan(/* retry = */ false); } private LeAudioGroupDescriptor getGroupDescriptor(int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { return mGroupDescriptors.get(groupId); } finally { mGroupLock.unlock(); } } private LeAudioDeviceDescriptor getDeviceDescriptor(BluetoothDevice device) { synchronized (mGroupLock) { mGroupLock.lock(); try { return mDeviceDescriptors.get(device); } finally { mGroupLock.unlock(); } } private void handleGroupNodeAdded(BluetoothDevice device, int groupId) { synchronized (mGroupLock) { mGroupLock.lock(); try { if (DBG) { Log.d(TAG, "Device " + device + " added to group " + groupId); } Loading Loading @@ -3475,6 +3570,8 @@ public class LeAudioService extends ProfileService { deviceDescriptor.mGroupId = groupId; notifyGroupNodeAdded(device, groupId); } finally { mGroupLock.unlock(); } if (mBluetoothEnabled) { Loading Loading @@ -3507,7 +3604,8 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "Removing device " + device + " grom group " + groupId); } synchronized (mGroupLock) { mGroupLock.lock(); try { LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(groupId); if (groupDescriptor == null) { Log.e(TAG, "handleGroupNodeRemoved: No valid descriptor for group: " + groupId); Loading Loading @@ -3551,6 +3649,8 @@ public class LeAudioService extends ProfileService { } } notifyGroupNodeRemoved(device, groupId); } finally { mGroupLock.unlock(); } setAuthorizationForRelatedProfiles(device, false); Loading Loading @@ -4617,7 +4717,8 @@ public class LeAudioService extends ProfileService { + mLeAudioInbandRingtoneSupportedByPlatform); int numberOfUngroupedDevs = 0; synchronized (mGroupLock) { mGroupLock.lock(); try { for (Map.Entry<Integer, LeAudioGroupDescriptor> groupEntry : mGroupDescriptors.entrySet()) { LeAudioGroupDescriptor groupDescriptor = groupEntry.getValue(); Loading Loading @@ -4661,6 +4762,8 @@ public class LeAudioService extends ProfileService { ProfileService.println(sb, " mDirection: " + deviceDescriptor.mDirection); } } } finally { mGroupLock.unlock(); } if (numberOfUngroupedDevs > 0) { Loading
flags/leaudio.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -159,3 +159,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "leaudio_api_synchronized_block_fix" namespace: "bluetooth" description: "Fix possible deadlocks when synchronizing LeAudioService states" bug: "326295400" metadata { purpose: PURPOSE_BUGFIX } }