diff options
author | Jay Shrauner <shrauner@google.com> | 2014-08-14 09:59:37 -0700 |
---|---|---|
committer | Jay Shrauner <shrauner@google.com> | 2014-08-14 14:04:41 -0700 |
commit | 899c8f2ba668080bc663732f610b683222a1bb77 (patch) | |
tree | 2958359da2b343b69936c455953fb7c182efbb95 | |
parent | 3718dcb345e77e421ab18a760e48f0c3a760fcca (diff) |
Prevent ConcurrentModificationExceptions
Switch from HashSets to Sets backed by ConcurrentHashMaps, and from
ArrayLists to CopyOnWriteArrayLists, to prevent exceptions when listeners
remove themselves in their callback while iterating through the set or list.
Bug:17030803
Change-Id: I99511e56d77526796679e2840437d0ea47062830
-rw-r--r-- | InCallUI/src/com/android/incallui/InCallPresenter.java | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java index 66890eb8c..23775212a 100644 --- a/InCallUI/src/com/android/incallui/InCallPresenter.java +++ b/InCallUI/src/com/android/incallui/InCallPresenter.java @@ -29,13 +29,13 @@ import android.view.Surface; import android.view.View; import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; /** * Takes updates from the CallList and notifies the InCallActivity (UI) @@ -50,11 +50,21 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { private static InCallPresenter sInCallPresenter; - private final Set<InCallStateListener> mListeners = Sets.newHashSet(); - private final ArrayList<IncomingCallListener> mIncomingCallListeners = Lists.newArrayList(); - private final Set<InCallDetailsListener> mDetailsListeners = Sets.newHashSet(); - private final Set<InCallOrientationListener> mOrientationListeners = Sets.newHashSet(); - private final Set<InCallEventListener> mInCallEventListeners = 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<InCallStateListener> mListeners = Collections.newSetFromMap( + new ConcurrentHashMap<InCallStateListener, Boolean>(8, 0.9f, 1)); + private final List<IncomingCallListener> mIncomingCallListeners = + new CopyOnWriteArrayList<IncomingCallListener>(); + private final Set<InCallDetailsListener> mDetailsListeners = Collections.newSetFromMap( + new ConcurrentHashMap<InCallDetailsListener, Boolean>(8, 0.9f, 1)); + private final Set<InCallOrientationListener> mOrientationListeners = Collections.newSetFromMap( + new ConcurrentHashMap<InCallOrientationListener, Boolean>(8, 0.9f, 1)); + private final Set<InCallEventListener> mInCallEventListeners = Collections.newSetFromMap( + new ConcurrentHashMap<InCallEventListener, Boolean>(8, 0.9f, 1)); private AudioModeProvider mAudioModeProvider; private StatusBarNotifier mStatusBarNotifier; @@ -400,8 +410,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { } public void removeIncomingCallListener(IncomingCallListener listener) { - Preconditions.checkNotNull(listener); - mIncomingCallListeners.remove(listener); + if (listener != null) { + mIncomingCallListeners.remove(listener); + } } public void addListener(InCallStateListener listener) { @@ -410,8 +421,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { } public void removeListener(InCallStateListener listener) { - Preconditions.checkNotNull(listener); - mListeners.remove(listener); + if (listener != null) { + mListeners.remove(listener); + } } public void addDetailsListener(InCallDetailsListener listener) { @@ -420,8 +432,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { } public void removeDetailsListener(InCallDetailsListener listener) { - Preconditions.checkNotNull(listener); - mDetailsListeners.remove(listener); + if (listener != null) { + mDetailsListeners.remove(listener); + } } public void addOrientationListener(InCallOrientationListener listener) { @@ -430,8 +443,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { } public void removeOrientationListener(InCallOrientationListener listener) { - Preconditions.checkNotNull(listener); - mOrientationListeners.remove(listener); + if (listener != null) { + mOrientationListeners.remove(listener); + } } public void addInCallEventListener(InCallEventListener listener) { @@ -440,8 +454,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { } public void removeInCallEventListener(InCallEventListener listener) { - Preconditions.checkNotNull(listener); - mInCallEventListeners.remove(listener); + if (listener != null) { + mInCallEventListeners.remove(listener); + } } public ProximitySensor getProximitySensor() { |