Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7aee46e5 authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Automerger Merge Worker
Browse files

Merge "Remove leaudio_api_synchronized_block_fix" into main am: 187eec2b

parents d4fed766 187eec2b
Loading
Loading
Loading
Loading
+39 −196
Original line number Original line Diff line number Diff line
@@ -22,7 +22,6 @@ import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;


import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;
import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;
import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask;
import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask;
import static com.android.bluetooth.flags.Flags.leaudioApiSynchronizedBlockFix;
import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState;
import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastFeatureSupport;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastFeatureSupport;
@@ -162,12 +161,9 @@ public class LeAudioService extends ProfileService {
    private volatile BluetoothDevice mActiveBroadcastAudioDevice;
    private volatile BluetoothDevice mActiveBroadcastAudioDevice;
    private BluetoothDevice mExposedActiveDevice;
    private BluetoothDevice mExposedActiveDevice;
    private LeAudioCodecConfig mLeAudioCodecConfig;
    private LeAudioCodecConfig mLeAudioCodecConfig;
    private final ReentrantLock mGroupLock = new ReentrantLock();
    private final ReentrantReadWriteLock mGroupReadWriteLock = new ReentrantReadWriteLock();
    private final ReentrantReadWriteLock mGroupReadWriteLock = new ReentrantReadWriteLock();
    private final Lock mGroupReadLock =
    private final Lock mGroupReadLock = mGroupReadWriteLock.readLock();
            leaudioApiSynchronizedBlockFix() ? mGroupReadWriteLock.readLock() : mGroupLock;
    private final Lock mGroupWriteLock = mGroupReadWriteLock.writeLock();
    private final Lock mGroupWriteLock =
            leaudioApiSynchronizedBlockFix() ? mGroupReadWriteLock.writeLock() : mGroupLock;
    ServiceFactory mServiceFactory = new ServiceFactory();
    ServiceFactory mServiceFactory = new ServiceFactory();


    private final LeAudioNativeInterface mNativeInterface;
    private final LeAudioNativeInterface mNativeInterface;
@@ -585,12 +581,10 @@ public class LeAudioService extends ProfileService {
                    sm.cleanup();
                    sm.cleanup();
                }
                }
            } finally {
            } finally {
                if (Flags.leaudioApiSynchronizedBlockFix()) {
                // Upgrade to write lock
                // Upgrade to write lock
                mGroupReadLock.unlock();
                mGroupReadLock.unlock();
                mGroupWriteLock.lock();
                mGroupWriteLock.lock();
            }
            }
            }
            mDeviceDescriptors.clear();
            mDeviceDescriptors.clear();
            mGroupDescriptors.clear();
            mGroupDescriptors.clear();
        } finally {
        } finally {
@@ -757,18 +751,11 @@ public class LeAudioService extends ProfileService {
                return false;
                return false;
            }
            }


            if (!Flags.leaudioApiSynchronizedBlockFix()) {
                sm.sendMessage(LeAudioStateMachine.CONNECT);
            }

        } finally {
        } finally {
            mGroupWriteLock.unlock();
            mGroupWriteLock.unlock();
        }
        }


        if (Flags.leaudioApiSynchronizedBlockFix()) {
        sm.sendMessage(LeAudioStateMachine.CONNECT);
        sm.sendMessage(LeAudioStateMachine.CONNECT);
        }

        return true;
        return true;
    }
    }


@@ -778,8 +765,8 @@ public class LeAudioService extends ProfileService {
     * @param device is the device with which we would like to disconnect LE Audio
     * @param device is the device with which we would like to disconnect LE Audio
     * @return true if profile disconnected, false if device not connected over LE Audio
     * @return true if profile disconnected, false if device not connected over LE Audio
     */
     */
    boolean disconnectV2(BluetoothDevice device) {
    public boolean disconnect(BluetoothDevice device) {
        Log.d(TAG, "disconnectV2(): " + device);
        Log.d(TAG, "disconnect(): " + device);


        LeAudioStateMachine sm = null;
        LeAudioStateMachine sm = null;


@@ -805,41 +792,6 @@ public class LeAudioService extends ProfileService {
        return true;
        return true;
    }
    }


    /**
     * Disconnects LE Audio for the remote bluetooth device
     *
     * @param device is the device with which we would like to disconnect LE Audio
     * @return true if profile disconnected, false if device not connected over LE Audio
     */
    public boolean disconnect(BluetoothDevice device) {
        if (Flags.leaudioApiSynchronizedBlockFix()) {
            return disconnectV2(device);
        }

        Log.d(TAG, "disconnect(): " + device);

        mGroupReadLock.lock();
        try {
            LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device);
            if (descriptor == null) {
                Log.e(TAG, "disconnect: No valid descriptor for device: " + device);
                return false;
            }

            LeAudioStateMachine sm = descriptor.mStateMachine;
            if (sm == null) {
                Log.e(TAG, "Ignored disconnect request for " + device + " : no state machine");
                return false;
            }

            sm.sendMessage(LeAudioStateMachine.DISCONNECT);
        } finally {
            mGroupReadLock.unlock();
        }

        return true;
    }

    public List<BluetoothDevice> getConnectedDevices() {
    public List<BluetoothDevice> getConnectedDevices() {
        mGroupReadLock.lock();
        mGroupReadLock.lock();
        try {
        try {
@@ -3711,7 +3663,6 @@ public class LeAudioService extends ProfileService {
        }
        }


        mGroupReadLock.lock();
        mGroupReadLock.lock();
        try {
        try {
        try {
            LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device);
            LeAudioDeviceDescriptor descriptor = getDeviceDescriptor(device);
            if (descriptor == null) {
            if (descriptor == null) {
@@ -3738,18 +3689,10 @@ public class LeAudioService extends ProfileService {
                return;
                return;
            }
            }
        } finally {
        } finally {
                // Reduce size of critical section when this feature is enabled
                if (Flags.leaudioApiSynchronizedBlockFix()) {
            mGroupReadLock.unlock();
            mGroupReadLock.unlock();
        }
        }
            }
        removeStateMachine(device);
        removeStateMachine(device);
        removeAuthorizationInfoForRelatedProfiles(device);
        removeAuthorizationInfoForRelatedProfiles(device);
        } finally {
            if (!Flags.leaudioApiSynchronizedBlockFix()) {
                mGroupReadLock.unlock();
            }
        }
    }
    }


    private void removeStateMachine(BluetoothDevice device) {
    private void removeStateMachine(BluetoothDevice device) {
@@ -3776,18 +3719,15 @@ public class LeAudioService extends ProfileService {
                sm.cleanup();
                sm.cleanup();
                descriptor.mStateMachine = null;
                descriptor.mStateMachine = null;
            } finally {
            } finally {
                if (Flags.leaudioApiSynchronizedBlockFix()) {
                // Upgrade to write lock
                // Upgrade to write lock
                mGroupReadLock.unlock();
                mGroupReadLock.unlock();
                mGroupWriteLock.lock();
                mGroupWriteLock.lock();
            }
            }
            }
            mDeviceDescriptors.remove(device);
            mDeviceDescriptors.remove(device);
            if (!isScannerNeeded()) {
            if (!isScannerNeeded()) {
                stopAudioServersBackgroundScan();
                stopAudioServersBackgroundScan();
            }
            }
        } finally {
        } finally {
            /* Note, when flag is disabled, mGroupWriteLock == mGroupReadLock */
            mGroupWriteLock.unlock();
            mGroupWriteLock.unlock();
        }
        }
    }
    }
@@ -3832,8 +3772,8 @@ public class LeAudioService extends ProfileService {
    }
    }


    /** Process a change for disconnection of a device. */
    /** Process a change for disconnection of a device. */
    synchronized void deviceDisconnectedV2(BluetoothDevice device, boolean hasFallbackDevice) {
    public synchronized void deviceDisconnected(BluetoothDevice device, boolean hasFallbackDevice) {
        Log.d(TAG, "deviceDisconnectedV2 " + device);
        Log.d(TAG, "deviceDisconnected " + device);


        int groupId = LE_AUDIO_GROUP_ID_INVALID;
        int groupId = LE_AUDIO_GROUP_ID_INVALID;
        mGroupReadLock.lock();
        mGroupReadLock.lock();
@@ -3912,88 +3852,6 @@ public class LeAudioService extends ProfileService {
        }
        }
    }
    }


    /** Process a change for disconnection of a device. */
    public synchronized void deviceDisconnected(BluetoothDevice device, boolean hasFallbackDevice) {
        if (Flags.leaudioApiSynchronizedBlockFix()) {
            deviceDisconnectedV2(device, hasFallbackDevice);
            return;
        }

        Log.d(TAG, "deviceDisconnected " + device);

        mGroupReadLock.lock();
        try {
            LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(device);
            if (deviceDescriptor == null) {
                Log.e(TAG, "deviceDisconnected: No valid descriptor for device: " + device);
                return;
            }

            int bondState = mAdapterService.getBondState(device);
            if (bondState == BluetoothDevice.BOND_NONE) {
                Log.d(TAG, device + " is unbond. Remove state machine");
                removeStateMachine(device);
                removeAuthorizationInfoForRelatedProfiles(device);
            }

            if (!isScannerNeeded()) {
                stopAudioServersBackgroundScan();
            }

            LeAudioGroupDescriptor descriptor = getGroupDescriptor(deviceDescriptor.mGroupId);
            if (descriptor == null) {
                Log.e(
                        TAG,
                        "deviceDisconnected: no descriptors for group: "
                                + deviceDescriptor.mGroupId);
                return;
            }

            List<BluetoothDevice> connectedDevices =
                    getConnectedPeerDevices(deviceDescriptor.mGroupId);
            /* Let's check if the last connected device is really connected */
            if (connectedDevices.size() == 1
                    && Objects.equals(
                            connectedDevices.get(0), descriptor.mLostLeadDeviceWhileStreaming)) {
                clearLostDevicesWhileStreaming(descriptor);
                return;
            }

            if (getConnectedPeerDevices(deviceDescriptor.mGroupId).isEmpty()) {
                descriptor.mIsConnected = false;
                descriptor.mInactivatedDueToContextType = false;
                if (descriptor.isActive()) {
                    /* Notify Native layer */
                    removeActiveDevice(hasFallbackDevice);
                    descriptor.setActiveState(ACTIVE_STATE_INACTIVE);
                    /* Update audio framework */
                    updateActiveDevices(
                            deviceDescriptor.mGroupId,
                            descriptor.mDirection,
                            descriptor.mDirection,
                            false,
                            hasFallbackDevice,
                            false);
                    return;
                }
            }

            if (descriptor.isActive()
                    || Objects.equals(mActiveAudioOutDevice, device)
                    || Objects.equals(mActiveAudioInDevice, device)) {
                updateActiveDevices(
                        deviceDescriptor.mGroupId,
                        descriptor.mDirection,
                        descriptor.mDirection,
                        descriptor.isActive(),
                        hasFallbackDevice,
                        false);
            }
        } finally {
            mGroupReadLock.unlock();
        }
    }

    /**
    /**
     * Check whether can connect to a peer device. The check considers a number of factors during
     * Check whether can connect to a peer device. The check considers a number of factors during
     * the evaluation.
     * the evaluation.
@@ -4438,18 +4296,10 @@ public class LeAudioService extends ProfileService {
        mBluetoothEnabled = true;
        mBluetoothEnabled = true;


        mGroupReadLock.lock();
        mGroupReadLock.lock();
        try {
        try {
        try {
            if (mDeviceDescriptors.isEmpty()) {
            if (mDeviceDescriptors.isEmpty()) {
                return;
                return;
            }
            }
            } finally {
                if (!Flags.leaudioApiSynchronizedBlockFix()) {
                    // Keep previous behavior where a lock is released and acquired immediately
                    mGroupReadLock.unlock();
                    mGroupReadLock.lock();
                }
            }
            for (BluetoothDevice device : mDeviceDescriptors.keySet()) {
            for (BluetoothDevice device : mDeviceDescriptors.keySet()) {
                if (getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
                if (getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
                    setAuthorizationForRelatedProfiles(device, true);
                    setAuthorizationForRelatedProfiles(device, true);
@@ -4588,10 +4438,6 @@ public class LeAudioService extends ProfileService {
        }
        }
    }
    }


    // When leaudioApiSynchronizedBlockFix is false, mGroupDescriptors is used within a
    // mGroupReadLock (same as mGroupWriteLock).
    // TODO(b/326295400): Remove SuppressLint
    @SuppressLint("GuardedBy")
    private void handleGroupNodeRemoved(BluetoothDevice device, int groupId) {
    private void handleGroupNodeRemoved(BluetoothDevice device, int groupId) {
        Log.d(TAG, "Removing device " + device + " grom group " + groupId);
        Log.d(TAG, "Removing device " + device + " grom group " + groupId);


@@ -4630,9 +4476,6 @@ public class LeAudioService extends ProfileService {
                        || Objects.equals(device, mActiveAudioInDevice)) {
                        || Objects.equals(device, mActiveAudioInDevice)) {
                    handleGroupTransitToInactive(groupId);
                    handleGroupTransitToInactive(groupId);
                }
                }
                if (!Flags.leaudioApiSynchronizedBlockFix()) {
                    mGroupDescriptors.remove(groupId);
                }


                if (mUnicastGroupIdDeactivatedForBroadcastTransition == groupId) {
                if (mUnicastGroupIdDeactivatedForBroadcastTransition == groupId) {
                    updateFallbackUnicastGroupIdForBroadcast(LE_AUDIO_GROUP_ID_INVALID);
                    updateFallbackUnicastGroupIdForBroadcast(LE_AUDIO_GROUP_ID_INVALID);
@@ -4643,7 +4486,7 @@ public class LeAudioService extends ProfileService {
            mGroupReadLock.unlock();
            mGroupReadLock.unlock();
        }
        }


        if (isGroupEmpty && Flags.leaudioApiSynchronizedBlockFix()) {
        if (isGroupEmpty) {
            mGroupWriteLock.lock();
            mGroupWriteLock.lock();
            try {
            try {
                mGroupDescriptors.remove(groupId);
                mGroupDescriptors.remove(groupId);
+0 −7
Original line number Original line Diff line number Diff line
@@ -1012,13 +1012,6 @@ public class LeAudioServiceTest {
        verify(mMcpService, times(1)).removeDeviceAuthorizationInfo(mLeftDevice);
        verify(mMcpService, times(1)).removeDeviceAuthorizationInfo(mLeftDevice);
    }
    }


    @Test
    public void testAuthorizationInfoRemovedFromTbsMcsOnUnbondEventsWithSynchBlockFixFlag() {
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_API_SYNCHRONIZED_BLOCK_FIX);

        testAuthorizationInfoRemovedFromTbsMcsOnUnbondEvents();
    }

    /**
    /**
     * Test that a CONNECTION_STATE_DISCONNECTED Le Audio stack event will remove the state machine
     * Test that a CONNECTION_STATE_DISCONNECTED Le Audio stack event will remove the state machine
     * only if the device is unbond.
     * only if the device is unbond.
+0 −10
Original line number Original line Diff line number Diff line
@@ -101,16 +101,6 @@ flag {
    }
    }
}
}


flag {
    name: "leaudio_api_synchronized_block_fix"
    namespace: "bluetooth"
    description: "Fix possible deadlocks when synchronizing LeAudioService states"
    bug: "326295400"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
flag {
    name: "run_ble_audio_ticks_in_worker_thread"
    name: "run_ble_audio_ticks_in_worker_thread"
    namespace: "bluetooth"
    namespace: "bluetooth"