Merge "DO NOT MERGE Don't lock listener delivery" into rvc-dev
diff --git a/location/java/android/location/AbstractListenerManager.java b/location/java/android/location/AbstractListenerManager.java
index 3dc7cfc..36b8689 100644
--- a/location/java/android/location/AbstractListenerManager.java
+++ b/location/java/android/location/AbstractListenerManager.java
@@ -85,11 +85,13 @@
         }
     }
 
-    @GuardedBy("mListeners")
-    private final ArrayMap<Object, Registration<TRequest, TListener>> mListeners =
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private volatile ArrayMap<Object, Registration<TRequest, TListener>> mListeners =
             new ArrayMap<>();
 
-    @GuardedBy("mListeners")
+    @GuardedBy("mLock")
     @Nullable
     private TRequest mMergedRequest;
 
@@ -129,10 +131,16 @@
             throws RemoteException {
         Preconditions.checkNotNull(registration);
 
-        synchronized (mListeners) {
+        synchronized (mLock) {
             boolean initialRequest = mListeners.isEmpty();
 
-            Registration<TRequest, TListener> oldRegistration = mListeners.put(key, registration);
+            ArrayMap<Object, Registration<TRequest, TListener>> newListeners = new ArrayMap<>(
+                    mListeners.size() + 1);
+            newListeners.putAll(mListeners);
+            Registration<TRequest, TListener> oldRegistration = newListeners.put(key,
+                    registration);
+            mListeners = newListeners;
+
             if (oldRegistration != null) {
                 oldRegistration.unregister();
             }
@@ -151,8 +159,12 @@
     }
 
     public void removeListener(Object listener) throws RemoteException {
-        synchronized (mListeners) {
-            Registration<TRequest, TListener> oldRegistration = mListeners.remove(listener);
+        synchronized (mLock) {
+            ArrayMap<Object, Registration<TRequest, TListener>> newListeners = new ArrayMap<>(
+                    mListeners);
+            Registration<TRequest, TListener> oldRegistration = newListeners.remove(listener);
+            mListeners = newListeners;
+
             if (oldRegistration == null) {
                 return;
             }
@@ -190,18 +202,16 @@
     }
 
     protected void execute(Consumer<TListener> operation) {
-        synchronized (mListeners) {
-            for (Registration<TRequest, TListener> registration : mListeners.values()) {
-                registration.execute(operation);
-            }
+        for (Registration<TRequest, TListener> registration : mListeners.values()) {
+            registration.execute(operation);
         }
     }
 
-    @GuardedBy("mListeners")
+    @GuardedBy("mLock")
     @SuppressWarnings("unchecked")
     @Nullable
     private TRequest mergeRequests() {
-        Preconditions.checkState(Thread.holdsLock(mListeners));
+        Preconditions.checkState(Thread.holdsLock(mLock));
 
         if (mListeners.isEmpty()) {
             return null;