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

Commit c46c161f authored by Hall Liu's avatar Hall Liu
Browse files

Fix locking for BluetoothDeviceManager

Lock on BluetoothDeviceManager's lock when fetching a list of available
devices. The previous implementation failed to take into account that
the return value of HashMap#values() is a view into the map, and
therefore can't be read while the base map is modified.

Fix is to create a copy of the list while still inside the synchronized
block. Also add a few more locks around the hashmap.

Change-Id: I336618a4cd42d74a70bad9c2075ea4de89a35240
Fixes: 110411424
Test: manual testing, unit tests
parent 87c0eaff
Loading
Loading
Loading
Loading
+12 −3
Original line number Original line Diff line number Diff line
@@ -30,7 +30,9 @@ import com.android.server.telecom.BluetoothAdapterProxy;
import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.TelecomSystem;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.LinkedList;
import java.util.List;
import java.util.List;
@@ -103,11 +105,16 @@ public class BluetoothDeviceManager {
    }
    }


    public int getNumConnectedDevices() {
    public int getNumConnectedDevices() {
        synchronized (mLock) {
            return mConnectedDevicesByAddress.size();
            return mConnectedDevicesByAddress.size();
        }
        }
    }


    public Collection<BluetoothDevice> getConnectedDevices() {
    public Collection<BluetoothDevice> getConnectedDevices() {
        return mConnectedDevicesByAddress.values();
        synchronized (mLock) {
            return Collections.unmodifiableCollection(
                    new ArrayList<>(mConnectedDevicesByAddress.values()));
        }
    }
    }


    public String getMostRecentlyConnectedDevice(String excludeAddress) {
    public String getMostRecentlyConnectedDevice(String excludeAddress) {
@@ -131,8 +138,10 @@ public class BluetoothDeviceManager {
    }
    }


    public BluetoothDevice getDeviceFromAddress(String address) {
    public BluetoothDevice getDeviceFromAddress(String address) {
        synchronized (mLock) {
            return mConnectedDevicesByAddress.get(address);
            return mConnectedDevicesByAddress.get(address);
        }
        }
    }


    void onDeviceConnected(BluetoothDevice device) {
    void onDeviceConnected(BluetoothDevice device) {
        synchronized (mLock) {
        synchronized (mLock) {
+1 −4
Original line number Original line Diff line number Diff line
@@ -33,9 +33,7 @@ import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
import com.android.server.telecom.Timeouts;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedHashSet;
@@ -572,8 +570,7 @@ public class BluetoothRouteManager extends StateMachine {
    }
    }


    public Collection<BluetoothDevice> getConnectedDevices() {
    public Collection<BluetoothDevice> getConnectedDevices() {
        return Collections.unmodifiableCollection(
        return mDeviceManager.getConnectedDevices();
                new ArrayList<>(mDeviceManager.getConnectedDevices()));
    }
    }


    private String connectHfpAudio(String address) {
    private String connectHfpAudio(String address) {