Use CopyOnWriteArrayList to avoid ConcurrentModificationException
Bug: 149362541 Test: make -j42 RunSettingsLibRoboTests Change-Id: I9bed14c0141a896ec91d2354df09bb5aaa432dfb
This commit is contained in:
@@ -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,18 +74,14 @@ public class LocalMediaManager implements BluetoothCallback {
|
||||
* Register to start receiving callbacks for MediaDevice events.
|
||||
*/
|
||||
public void registerCallback(DeviceCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
mCallbacks.add(callback);
|
||||
}
|
||||
mCallbacks.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister to stop receiving callbacks for MediaDevice events
|
||||
*/
|
||||
public void unregisterCallback(DeviceCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
mCallbacks.remove(callback);
|
||||
}
|
||||
mCallbacks.remove(callback);
|
||||
}
|
||||
|
||||
public LocalMediaManager(Context context, String packageName, Notification notification) {
|
||||
@@ -152,10 +149,8 @@ public class LocalMediaManager implements BluetoothCallback {
|
||||
}
|
||||
|
||||
void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
|
||||
synchronized (mCallbacks) {
|
||||
for (DeviceCallback callback : mCallbacks) {
|
||||
callback.onSelectedDeviceStateChanged(device, state);
|
||||
}
|
||||
for (DeviceCallback callback : getCallbacks()) {
|
||||
callback.onSelectedDeviceStateChanged(device, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,19 +164,15 @@ public class LocalMediaManager implements BluetoothCallback {
|
||||
}
|
||||
|
||||
void dispatchDeviceListUpdate() {
|
||||
synchronized (mCallbacks) {
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
for (DeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
|
||||
}
|
||||
Collections.sort(mMediaDevices, COMPARATOR);
|
||||
for (DeviceCallback callback : getCallbacks()) {
|
||||
callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchDeviceAttributesChanged() {
|
||||
synchronized (mCallbacks) {
|
||||
for (DeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceAttributesChanged();
|
||||
}
|
||||
for (DeviceCallback callback : getCallbacks()) {
|
||||
callback.onDeviceAttributesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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,18 +43,14 @@ public abstract class MediaManager {
|
||||
}
|
||||
|
||||
protected void registerCallback(MediaDeviceCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
if (!mCallbacks.contains(callback)) {
|
||||
mCallbacks.add(callback);
|
||||
}
|
||||
if (!mCallbacks.contains(callback)) {
|
||||
mCallbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
protected void unregisterCallback(MediaDeviceCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
if (mCallbacks.contains(callback)) {
|
||||
mCallbacks.remove(callback);
|
||||
}
|
||||
if (mCallbacks.contains(callback)) {
|
||||
mCallbacks.remove(callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,53 +75,45 @@ public abstract class MediaManager {
|
||||
}
|
||||
|
||||
protected void dispatchDeviceAdded(MediaDevice mediaDevice) {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceAdded(mediaDevice);
|
||||
}
|
||||
for (MediaDeviceCallback callback : getCallbacks()) {
|
||||
callback.onDeviceAdded(mediaDevice);
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchDeviceRemoved(MediaDevice mediaDevice) {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceRemoved(mediaDevice);
|
||||
}
|
||||
for (MediaDeviceCallback callback : getCallbacks()) {
|
||||
callback.onDeviceRemoved(mediaDevice);
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchDeviceListAdded() {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceListAdded(new ArrayList<>(mMediaDevices));
|
||||
}
|
||||
for (MediaDeviceCallback callback : getCallbacks()) {
|
||||
callback.onDeviceListAdded(new ArrayList<>(mMediaDevices));
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchDeviceListRemoved(List<MediaDevice> devices) {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceListRemoved(devices);
|
||||
}
|
||||
for (MediaDeviceCallback callback : getCallbacks()) {
|
||||
callback.onDeviceListRemoved(devices);
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchConnectedDeviceChanged(String id) {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onConnectedDeviceChanged(id);
|
||||
}
|
||||
for (MediaDeviceCallback callback : getCallbacks()) {
|
||||
callback.onConnectedDeviceChanged(id);
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchDataChanged() {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceAttributesChanged();
|
||||
}
|
||||
for (MediaDeviceCallback callback : getCallbacks()) {
|
||||
callback.onDeviceAttributesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<MediaDeviceCallback> getCallbacks() {
|
||||
return new CopyOnWriteArrayList<>(mCallbacks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for notifying device is added, removed and attributes changed.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user