summaryrefslogtreecommitdiff
path: root/InCallUI
diff options
context:
space:
mode:
authorJay Shrauner <shrauner@google.com>2014-08-14 13:30:28 -0700
committerJay Shrauner <shrauner@google.com>2014-08-15 13:41:54 -0700
commitcbbbfcba0c68498cde93da2e9b10e748cc5e91ef (patch)
treeb9fcca121814ba3be7a435ed20e18e285b42e554 /InCallUI
parenta920437f6af7b49669518d6e145ca444c6870560 (diff)
Prevent ConcurrentModificationExceptions
Use sets backed by ConcurrentHashMaps instead of HashSets, and CopyOnWriteArrayLists instead of ArrayLists, to prevent concurrent exceptions if listeners try to remove themselves in callbacks while iterating over the listeners. Bug:16325026 Change-Id: Ia86f5cafa1d844aa7927df8ff9b02b5574bdde2b
Diffstat (limited to 'InCallUI')
-rw-r--r--InCallUI/src/com/android/incallui/CallList.java19
-rw-r--r--InCallUI/src/com/android/incallui/InCallPresenter.java3
-rw-r--r--InCallUI/src/com/android/incallui/InCallVideoCallListenerNotifier.java32
3 files changed, 37 insertions, 17 deletions
diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java
index 66103e6ff..0927adc07 100644
--- a/InCallUI/src/com/android/incallui/CallList.java
+++ b/InCallUI/src/com/android/incallui/CallList.java
@@ -16,7 +16,6 @@
package com.android.incallui;
-import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.base.Preconditions;
@@ -26,9 +25,12 @@ import android.os.Message;
import android.telecomm.Phone;
import android.telephony.DisconnectCause;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* Maintains the list of active calls and notifies interested classes of changes to the call list
@@ -48,7 +50,13 @@ public class CallList implements InCallPhoneListener {
private final HashMap<String, Call> mCallById = new HashMap<>();
private final HashMap<android.telecomm.Call, Call> mCallByTelecommCall = new HashMap<>();
private final HashMap<String, List<String>> mCallTextReponsesMap = Maps.newHashMap();
- private final Set<Listener> mListeners = Sets.newHashSet();
+ /**
+ * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
+ * load factor before resizing, 1 means we only expect a single thread to
+ * access the map so make only a single shard
+ */
+ private final Set<Listener> mListeners = Collections.newSetFromMap(
+ new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
private final HashMap<String, List<CallUpdateListener>> mCallUpdateListenerMap = Maps
.newHashMap();
@@ -151,7 +159,7 @@ public class CallList implements InCallPhoneListener {
public void addCallUpdateListener(String callId, CallUpdateListener listener) {
List<CallUpdateListener> listeners = mCallUpdateListenerMap.get(callId);
if (listeners == null) {
- listeners = Lists.newArrayList();
+ listeners = new CopyOnWriteArrayList<CallUpdateListener>();
mCallUpdateListenerMap.put(callId, listeners);
}
listeners.add(listener);
@@ -180,8 +188,9 @@ public class CallList implements InCallPhoneListener {
}
public void removeListener(Listener listener) {
- Preconditions.checkNotNull(listener);
- mListeners.remove(listener);
+ if (listener != null) {
+ mListeners.remove(listener);
+ }
}
/**
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 23775212a..38b5f5400 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -57,8 +57,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
private final Set<InCallStateListener> mListeners = Collections.newSetFromMap(
new ConcurrentHashMap<InCallStateListener, Boolean>(8, 0.9f, 1));
- private final List<IncomingCallListener> mIncomingCallListeners =
- new CopyOnWriteArrayList<IncomingCallListener>();
+ private final List<IncomingCallListener> mIncomingCallListeners = new CopyOnWriteArrayList<>();
private final Set<InCallDetailsListener> mDetailsListeners = Collections.newSetFromMap(
new ConcurrentHashMap<InCallDetailsListener, Boolean>(8, 0.9f, 1));
private final Set<InCallOrientationListener> mOrientationListeners = Collections.newSetFromMap(
diff --git a/InCallUI/src/com/android/incallui/InCallVideoCallListenerNotifier.java b/InCallUI/src/com/android/incallui/InCallVideoCallListenerNotifier.java
index 0e64cd790..9f3f062cd 100644
--- a/InCallUI/src/com/android/incallui/InCallVideoCallListenerNotifier.java
+++ b/InCallUI/src/com/android/incallui/InCallVideoCallListenerNotifier.java
@@ -17,9 +17,10 @@
package com.android.incallui;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
+import java.util.Collections;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* Class used by {@link InCallService.VideoCallListener} to notify interested parties of incoming
@@ -31,10 +32,18 @@ public class InCallVideoCallListenerNotifier {
*/
private static InCallVideoCallListenerNotifier sInstance = new InCallVideoCallListenerNotifier();
+ /**
+ * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
+ * load factor before resizing, 1 means we only expect a single thread to
+ * access the map so make only a single shard
+ */
private final Set<SessionModificationListener> mSessionModificationListeners =
- Sets.newHashSet();
- private final Set<VideoEventListener> mVideoEventListeners = Sets.newHashSet();
- private final Set<SurfaceChangeListener> mSurfaceChangeListeners = Sets.newHashSet();
+ Collections.newSetFromMap(new ConcurrentHashMap<SessionModificationListener, Boolean>
+ (8, 0.9f, 1));
+ private final Set<VideoEventListener> mVideoEventListeners = Collections.newSetFromMap(
+ new ConcurrentHashMap<VideoEventListener, Boolean>(8, 0.9f, 1));
+ private final Set<SurfaceChangeListener> mSurfaceChangeListeners = Collections.newSetFromMap(
+ new ConcurrentHashMap<SurfaceChangeListener, Boolean>(8, 0.9f, 1));
/**
* Static singleton accessor method.
@@ -65,8 +74,9 @@ public class InCallVideoCallListenerNotifier {
* @param listener The listener.
*/
public void removeSessionModificationListener(SessionModificationListener listener) {
- Preconditions.checkNotNull(listener);
- mSessionModificationListeners.remove(listener);
+ if (listener != null) {
+ mSessionModificationListeners.remove(listener);
+ }
}
/**
@@ -85,8 +95,9 @@ public class InCallVideoCallListenerNotifier {
* @param listener The listener.
*/
public void removeVideoEventListener(VideoEventListener listener) {
- Preconditions.checkNotNull(listener);
- mVideoEventListeners.remove(listener);
+ if (listener != null) {
+ mVideoEventListeners.remove(listener);
+ }
}
/**
@@ -105,8 +116,9 @@ public class InCallVideoCallListenerNotifier {
* @param listener The listener.
*/
public void removeSurfaceChangeListener(SurfaceChangeListener listener) {
- Preconditions.checkNotNull(listener);
- mSurfaceChangeListeners.remove(listener);
+ if (listener != null) {
+ mSurfaceChangeListeners.remove(listener);
+ }
}
/**