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

Commit 0bc952a4 authored by davidln's avatar davidln
Browse files

Concurrent collections for Bluetooth callbacks.

This allows callback classes to remove themselves or add additional
callbacks in response to state change dispatches.

Bug: 129060225

Test: build and deploy, pair multiple devices (w/code path that hits
 problem case), RunSettingsLibRoboTests

Change-Id: I8eed81bbc9c12321ec41b2491d006764e2e483d6
parent 06eb3c41
Loading
Loading
Loading
Loading
+41 −68
Original line number Diff line number Diff line
@@ -35,12 +35,12 @@ import androidx.annotation.VisibleForTesting;

import com.android.settingslib.R;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * BluetoothEventManager receives broadcasts and callbacks from the Bluetooth
@@ -56,7 +56,7 @@ public class BluetoothEventManager {
    private final Map<String, Handler> mHandlerMap;
    private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver();
    private final BroadcastReceiver mProfileBroadcastReceiver = new BluetoothBroadcastReceiver();
    private final Collection<BluetoothCallback> mCallbacks = new ArrayList<>();
    private final Collection<BluetoothCallback> mCallbacks = new CopyOnWriteArrayList<>();
    private final android.os.Handler mReceiverHandler;
    private final UserHandle mUserHandle;
    private final Context mContext;
@@ -93,8 +93,10 @@ public class BluetoothEventManager {
                new ConnectionStateChangedHandler());

        // Discovery broadcasts
        addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
        addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
        addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED,
                new ScanningStateChangedHandler(true));
        addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED,
                new ScanningStateChangedHandler(false));
        addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
        addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
        addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler());
@@ -128,17 +130,13 @@ public class BluetoothEventManager {

    /** Register to start receiving callbacks for Bluetooth events. */
    public void registerCallback(BluetoothCallback callback) {
        synchronized (mCallbacks) {
        mCallbacks.add(callback);
    }
    }

    /** Unregister to stop receiving callbacks for Bluetooth events. */
    public void unregisterCallback(BluetoothCallback callback) {
        synchronized (mCallbacks) {
        mCallbacks.remove(callback);
    }
    }

    @VisibleForTesting
    void registerProfileIntentReceiver() {
@@ -189,65 +187,50 @@ public class BluetoothEventManager {
    }

    void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
        synchronized (mCallbacks) {
        for (BluetoothCallback callback : mCallbacks) {
            callback.onDeviceAdded(cachedDevice);
        }
    }
    }

    void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
        synchronized (mCallbacks) {
        for (BluetoothCallback callback : mCallbacks) {
            callback.onDeviceDeleted(cachedDevice);
        }
    }
    }

    void dispatchProfileConnectionStateChanged(CachedBluetoothDevice device, int state,
            int bluetoothProfile) {
        synchronized (mCallbacks) {
        for (BluetoothCallback callback : mCallbacks) {
            callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
        }
    }
    }

    private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
        synchronized (mCallbacks) {
        for (BluetoothCallback callback : mCallbacks) {
            callback.onConnectionStateChanged(cachedDevice, state);
        }
    }
    }

    private void dispatchAudioModeChanged() {
        mDeviceManager.dispatchAudioModeChanged();
        synchronized (mCallbacks) {
        for (BluetoothCallback callback : mCallbacks) {
            callback.onAudioModeChanged();
        }
    }
    }

    private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice,
            int bluetoothProfile) {
        mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile);
        synchronized (mCallbacks) {
        for (BluetoothCallback callback : mCallbacks) {
            callback.onActiveDeviceChanged(activeDevice, bluetoothProfile);
        }
    }
    }

    private void dispatchAclStateChanged(CachedBluetoothDevice activeDevice,
            int state) {
        synchronized (mCallbacks) {
    private void dispatchAclStateChanged(CachedBluetoothDevice activeDevice, int state) {
        for (BluetoothCallback callback : mCallbacks) {
            callback.onAclConnectionStateChanged(activeDevice, state);
        }
    }
    }

    @VisibleForTesting
    void addHandler(String action, Handler handler) {
@@ -270,18 +253,15 @@ public class BluetoothEventManager {
    }

    private class AdapterStateChangedHandler implements Handler {
        public void onReceive(Context context, Intent intent,
                BluetoothDevice device) {
        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
                    BluetoothAdapter.ERROR);
            // update local profiles and get paired devices
            mLocalAdapter.setBluetoothStateInt(state);
            // send callback to update UI and possibly start scanning
            synchronized (mCallbacks) {
            for (BluetoothCallback callback : mCallbacks) {
                callback.onBluetoothStateChanged(state);
            }
            }
            // Inform CachedDeviceManager that the adapter state has changed
            mDeviceManager.onBluetoothStateChanged(state);
        }
@@ -293,13 +273,11 @@ public class BluetoothEventManager {
        ScanningStateChangedHandler(boolean started) {
            mStarted = started;
        }
        public void onReceive(Context context, Intent intent,
                BluetoothDevice device) {
            synchronized (mCallbacks) {

        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
            for (BluetoothCallback callback : mCallbacks) {
                callback.onScanningStateChanged(mStarted);
            }
            }
            mDeviceManager.onScanningStateChanged(mStarted);
        }
    }
@@ -350,8 +328,7 @@ public class BluetoothEventManager {
    }

    private class BondStateChangedHandler implements Handler {
        public void onReceive(Context context, Intent intent,
                BluetoothDevice device) {
        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
            if (device == null) {
                Log.e(TAG, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE");
                return;
@@ -365,11 +342,9 @@ public class BluetoothEventManager {
                cachedDevice = mDeviceManager.addDevice(device);
            }

            synchronized (mCallbacks) {
            for (BluetoothCallback callback : mCallbacks) {
                callback.onDeviceBondStateChanged(cachedDevice, bondState);
            }
            }
            cachedDevice.onBondingStateChanged(bondState);

            if (bondState == BluetoothDevice.BOND_NONE) {
@@ -410,7 +385,8 @@ public class BluetoothEventManager {
                    errorMsg = R.string.bluetooth_pairing_error_message;
                    break;
                default:
                    Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason);
                    Log.w(TAG,
                            "showUnbondMessage: Not displaying any message for reason: " + reason);
                    return;
            }
            BluetoothUtils.showError(context, name, errorMsg);
@@ -418,8 +394,7 @@ public class BluetoothEventManager {
    }

    private class ClassChangedHandler implements Handler {
        public void onReceive(Context context, Intent intent,
                BluetoothDevice device) {
        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
            if (cachedDevice != null) {
                cachedDevice.refresh();
@@ -428,8 +403,7 @@ public class BluetoothEventManager {
    }

    private class UuidChangedHandler implements Handler {
        public void onReceive(Context context, Intent intent,
                BluetoothDevice device) {
        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
            if (cachedDevice != null) {
                cachedDevice.onUuidChanged();
@@ -438,8 +412,7 @@ public class BluetoothEventManager {
    }

    private class BatteryLevelChangedHandler implements Handler {
        public void onReceive(Context context, Intent intent,
                BluetoothDevice device) {
        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
            if (cachedDevice != null) {
                cachedDevice.refresh();
+6 −11
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * CachedBluetoothDevice represents a remote Bluetooth device. It contains
@@ -74,7 +75,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>

    boolean mJustDiscovered;

    private final Collection<Callback> mCallbacks = new ArrayList<>();
    private final Collection<Callback> mCallbacks = new CopyOnWriteArrayList<>();

    /**
     * Last time a bt profile auto-connect was attempted.
@@ -678,24 +679,18 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
    }

    public void registerCallback(Callback callback) {
        synchronized (mCallbacks) {
        mCallbacks.add(callback);
    }
    }

    public void unregisterCallback(Callback callback) {
        synchronized (mCallbacks) {
        mCallbacks.remove(callback);
    }
    }

    void dispatchAttributesChanged() {
        synchronized (mCallbacks) {
        for (Callback callback : mCallbacks) {
            callback.onDeviceAttributesChanged();
        }
    }
    }

    @Override
    public String toString() {