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

Commit 574eeea2 authored by Henri Chataing's avatar Henri Chataing Committed by Gerrit Code Review
Browse files

Merge "Fix a2dp state machine java crash" into main

parents c3d0fd41 f2133c57
Loading
Loading
Loading
Loading
+46 −25
Original line number Original line Diff line number Diff line
@@ -51,6 +51,8 @@ import java.util.concurrent.ConcurrentHashMap;
public class A2dpSinkService extends ProfileService {
public class A2dpSinkService extends ProfileService {
    private static final String TAG = A2dpSinkService.class.getSimpleName();
    private static final String TAG = A2dpSinkService.class.getSimpleName();


    // This is also used as a lock for shared data in {@link A2dpSinkService}
    @GuardedBy("mDeviceStateMap")
    private final Map<BluetoothDevice, A2dpSinkStateMachine> mDeviceStateMap =
    private final Map<BluetoothDevice, A2dpSinkStateMachine> mDeviceStateMap =
            new ConcurrentHashMap<>(1);
            new ConcurrentHashMap<>(1);


@@ -116,10 +118,12 @@ public class A2dpSinkService extends ProfileService {
    public void stop() {
    public void stop() {
        setA2dpSinkService(null);
        setA2dpSinkService(null);
        mNativeInterface.cleanup();
        mNativeInterface.cleanup();
        synchronized (mDeviceStateMap) {
            for (A2dpSinkStateMachine stateMachine : mDeviceStateMap.values()) {
            for (A2dpSinkStateMachine stateMachine : mDeviceStateMap.values()) {
                stateMachine.quitNow();
                stateMachine.quitNow();
            }
            }
            mDeviceStateMap.clear();
            mDeviceStateMap.clear();
        }
        synchronized (mStreamHandlerLock) {
        synchronized (mStreamHandlerLock) {
            if (mA2dpSinkStreamHandler != null) {
            if (mA2dpSinkStreamHandler != null) {
                mA2dpSinkStreamHandler.cleanup();
                mA2dpSinkStreamHandler.cleanup();
@@ -362,7 +366,10 @@ public class A2dpSinkService extends ProfileService {
            throw new IllegalArgumentException("Null device");
            throw new IllegalArgumentException("Null device");
        }
        }


        A2dpSinkStateMachine stateMachine = mDeviceStateMap.get(device);
        A2dpSinkStateMachine stateMachine;
        synchronized (mDeviceStateMap) {
            stateMachine = mDeviceStateMap.get(device);
        }
        // a state machine instance doesn't exist. maybe it is already gone?
        // a state machine instance doesn't exist. maybe it is already gone?
        if (stateMachine == null) {
        if (stateMachine == null) {
            return false;
            return false;
@@ -389,7 +396,9 @@ public class A2dpSinkService extends ProfileService {
        if (stateMachine == null) {
        if (stateMachine == null) {
            return;
            return;
        }
        }
        synchronized (mDeviceStateMap) {
            mDeviceStateMap.remove(stateMachine.getDevice());
            mDeviceStateMap.remove(stateMachine.getDevice());
        }
        stateMachine.quitNow();
        stateMachine.quitNow();
    }
    }


@@ -400,6 +409,7 @@ public class A2dpSinkService extends ProfileService {
    protected A2dpSinkStateMachine getOrCreateStateMachine(BluetoothDevice device) {
    protected A2dpSinkStateMachine getOrCreateStateMachine(BluetoothDevice device) {
        A2dpSinkStateMachine newStateMachine =
        A2dpSinkStateMachine newStateMachine =
                new A2dpSinkStateMachine(mLooper, device, this, mNativeInterface);
                new A2dpSinkStateMachine(mLooper, device, this, mNativeInterface);
        synchronized (mDeviceStateMap) {
            A2dpSinkStateMachine existingStateMachine =
            A2dpSinkStateMachine existingStateMachine =
                    mDeviceStateMap.putIfAbsent(device, newStateMachine);
                    mDeviceStateMap.putIfAbsent(device, newStateMachine);
            // Given null is not a valid value in our map, ConcurrentHashMap will return null if the
            // Given null is not a valid value in our map, ConcurrentHashMap will return null if the
@@ -411,11 +421,14 @@ public class A2dpSinkService extends ProfileService {
            }
            }
            return existingStateMachine;
            return existingStateMachine;
        }
        }
    }


    @VisibleForTesting
    @VisibleForTesting
    protected A2dpSinkStateMachine getStateMachineForDevice(BluetoothDevice device) {
    protected A2dpSinkStateMachine getStateMachineForDevice(BluetoothDevice device) {
        synchronized (mDeviceStateMap) {
            return mDeviceStateMap.get(device);
            return mDeviceStateMap.get(device);
        }
        }
    }


    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        Log.d(TAG, "getDevicesMatchingConnectionStates(states=" + Arrays.toString(states) + ")");
        Log.d(TAG, "getDevicesMatchingConnectionStates(states=" + Arrays.toString(states) + ")");
@@ -451,7 +464,10 @@ public class A2dpSinkService extends ProfileService {
     */
     */
    public int getConnectionState(BluetoothDevice device) {
    public int getConnectionState(BluetoothDevice device) {
        if (device == null) return BluetoothProfile.STATE_DISCONNECTED;
        if (device == null) return BluetoothProfile.STATE_DISCONNECTED;
        A2dpSinkStateMachine stateMachine = mDeviceStateMap.get(device);
        A2dpSinkStateMachine stateMachine;
        synchronized (mDeviceStateMap) {
            stateMachine = mDeviceStateMap.get(device);
        }
        return (stateMachine == null)
        return (stateMachine == null)
                    ? BluetoothProfile.STATE_DISCONNECTED
                    ? BluetoothProfile.STATE_DISCONNECTED
                    : stateMachine.getState();
                    : stateMachine.getState();
@@ -501,6 +517,7 @@ public class A2dpSinkService extends ProfileService {
        super.dump(sb);
        super.dump(sb);
        ProfileService.println(sb, "Active Device = " + getActiveDevice());
        ProfileService.println(sb, "Active Device = " + getActiveDevice());
        ProfileService.println(sb, "Max Connected Devices = " + mMaxConnectedAudioDevices);
        ProfileService.println(sb, "Max Connected Devices = " + mMaxConnectedAudioDevices);
        synchronized (mDeviceStateMap) {
            ProfileService.println(sb, "Devices Tracked = " + mDeviceStateMap.size());
            ProfileService.println(sb, "Devices Tracked = " + mDeviceStateMap.size());
            for (A2dpSinkStateMachine stateMachine : mDeviceStateMap.values()) {
            for (A2dpSinkStateMachine stateMachine : mDeviceStateMap.values()) {
                ProfileService.println(
                ProfileService.println(
@@ -508,10 +525,14 @@ public class A2dpSinkService extends ProfileService {
                stateMachine.dump(sb);
                stateMachine.dump(sb);
            }
            }
        }
        }
    }


    BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
    BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
        if (device == null) return null;
        if (device == null) return null;
        A2dpSinkStateMachine stateMachine = mDeviceStateMap.get(device);
        A2dpSinkStateMachine stateMachine;
        synchronized (mDeviceStateMap) {
            stateMachine = mDeviceStateMap.get(device);
        }
        // a state machine instance doesn't exist. maybe it is already gone?
        // a state machine instance doesn't exist. maybe it is already gone?
        if (stateMachine == null) {
        if (stateMachine == null) {
            return null;
            return null;