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

Commit 8175bf2b authored by hughchen's avatar hughchen
Browse files

Use CopyOnWriteArrayList to avoid ConcurrentModificationException

Bug: 149362541
Test: make -j42 RunSettingsLibRoboTests
Change-Id: I9bed14c0141a896ec91d2354df09bb5aaa432dfb
parent 08883928
Loading
Loading
Loading
Loading
+15 −20
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
@@ -53,7 +54,7 @@ public class LocalMediaManager implements BluetoothCallback {
        int STATE_DISCONNECTED = 3;
    }

    private final Collection<DeviceCallback> mCallbacks = new ArrayList<>();
    private final Collection<DeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
    @VisibleForTesting
    final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback();

@@ -73,19 +74,15 @@ public class LocalMediaManager implements BluetoothCallback {
     * Register to start receiving callbacks for MediaDevice events.
     */
    public void registerCallback(DeviceCallback callback) {
        synchronized (mCallbacks) {
        mCallbacks.add(callback);
    }
    }

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

    public LocalMediaManager(Context context, String packageName, Notification notification) {
        mContext = context;
@@ -152,12 +149,10 @@ public class LocalMediaManager implements BluetoothCallback {
    }

    void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
        synchronized (mCallbacks) {
            for (DeviceCallback callback : mCallbacks) {
        for (DeviceCallback callback : getCallbacks()) {
            callback.onSelectedDeviceStateChanged(device, state);
        }
    }
    }

    /**
     * Start scan connected MediaDevice
@@ -169,21 +164,17 @@ public class LocalMediaManager implements BluetoothCallback {
    }

    void dispatchDeviceListUpdate() {
        synchronized (mCallbacks) {
        Collections.sort(mMediaDevices, COMPARATOR);
            for (DeviceCallback callback : mCallbacks) {
        for (DeviceCallback callback : getCallbacks()) {
            callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
        }
    }
    }

    void dispatchDeviceAttributesChanged() {
        synchronized (mCallbacks) {
            for (DeviceCallback callback : mCallbacks) {
        for (DeviceCallback callback : getCallbacks()) {
            callback.onDeviceAttributesChanged();
        }
    }
    }

    /**
     * Stop scan MediaDevice
@@ -270,6 +261,10 @@ public class LocalMediaManager implements BluetoothCallback {
                || device.isActiveDevice(BluetoothProfile.HEARING_AID);
    }

    private Collection<DeviceCallback> getCallbacks() {
        return new CopyOnWriteArrayList<>(mCallbacks);
    }

    class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
        @Override
        public void onDeviceAdded(MediaDevice device) {
+22 −33
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * MediaManager provide interface to get MediaDevice list.
@@ -30,7 +31,7 @@ public abstract class MediaManager {

    private static final String TAG = "MediaManager";

    protected final Collection<MediaDeviceCallback> mCallbacks = new ArrayList<>();
    protected final Collection<MediaDeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
    protected final List<MediaDevice> mMediaDevices = new ArrayList<>();

    protected Context mContext;
@@ -42,20 +43,16 @@ public abstract class MediaManager {
    }

    protected void registerCallback(MediaDeviceCallback callback) {
        synchronized (mCallbacks) {
        if (!mCallbacks.contains(callback)) {
            mCallbacks.add(callback);
        }
    }
    }

    protected void unregisterCallback(MediaDeviceCallback callback) {
        synchronized (mCallbacks) {
        if (mCallbacks.contains(callback)) {
            mCallbacks.remove(callback);
        }
    }
    }

    /**
     * Start scan connected MediaDevice
@@ -78,51 +75,43 @@ public abstract class MediaManager {
    }

    protected void dispatchDeviceAdded(MediaDevice mediaDevice) {
        synchronized (mCallbacks) {
            for (MediaDeviceCallback callback : mCallbacks) {
        for (MediaDeviceCallback callback : getCallbacks()) {
            callback.onDeviceAdded(mediaDevice);
        }
    }
    }

    protected void dispatchDeviceRemoved(MediaDevice mediaDevice) {
        synchronized (mCallbacks) {
            for (MediaDeviceCallback callback : mCallbacks) {
        for (MediaDeviceCallback callback : getCallbacks()) {
            callback.onDeviceRemoved(mediaDevice);
        }
    }
    }

    protected void dispatchDeviceListAdded() {
        synchronized (mCallbacks) {
            for (MediaDeviceCallback callback : mCallbacks) {
        for (MediaDeviceCallback callback : getCallbacks()) {
            callback.onDeviceListAdded(new ArrayList<>(mMediaDevices));
        }
    }
    }

    protected void dispatchDeviceListRemoved(List<MediaDevice> devices) {
        synchronized (mCallbacks) {
            for (MediaDeviceCallback callback : mCallbacks) {
        for (MediaDeviceCallback callback : getCallbacks()) {
            callback.onDeviceListRemoved(devices);
        }
    }
    }

    protected void dispatchConnectedDeviceChanged(String id) {
        synchronized (mCallbacks) {
            for (MediaDeviceCallback callback : mCallbacks) {
        for (MediaDeviceCallback callback : getCallbacks()) {
            callback.onConnectedDeviceChanged(id);
        }
    }
    }

    protected void dispatchDataChanged() {
        synchronized (mCallbacks) {
            for (MediaDeviceCallback callback : mCallbacks) {
        for (MediaDeviceCallback callback : getCallbacks()) {
            callback.onDeviceAttributesChanged();
        }
    }

    private Collection<MediaDeviceCallback> getCallbacks() {
        return new CopyOnWriteArrayList<>(mCallbacks);
    }

    /**