Merge "Fix projection status distribution" into qt-dev am: c8a3638547 am: fb6d4ff34e
am: c6d8548652

Change-Id: Ic2fe5dd0ca0ab0fffbc270ddb524f3a9fb80bac9
diff --git a/service/src/com/android/car/CarProjectionService.java b/service/src/com/android/car/CarProjectionService.java
index 144804e..25edc79 100644
--- a/service/src/com/android/car/CarProjectionService.java
+++ b/service/src/com/android/car/CarProjectionService.java
@@ -67,6 +67,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.car.BinderInterfaceContainer.BinderInterface;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
@@ -80,7 +81,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Random;
-import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * Car projection service allows to bound to projected app to boost it prioirity.
@@ -128,8 +128,8 @@
     @GuardedBy("mLock")
     private @Nullable String mCurrentProjectionPackage;
 
-    private final List<ICarProjectionStatusListener> mProjectionStatusListeners =
-            new CopyOnWriteArrayList<>();
+    private final BinderInterfaceContainer<ICarProjectionStatusListener>
+            mProjectionStatusListeners = new BinderInterfaceContainer<>();
 
     @GuardedBy("mLock")
     private final ProjectionKeyEventHandlerContainer mKeyEventHandlers;
@@ -431,7 +431,7 @@
     public void registerProjectionStatusListener(ICarProjectionStatusListener listener)
             throws RemoteException {
         ICarImpl.assertProjectionStatusPermission(mContext);
-        mProjectionStatusListeners.add(listener);
+        mProjectionStatusListeners.addBinder(listener);
 
         // Immediately notify listener with the current status.
         notifyProjectionStatusChanged(listener);
@@ -441,7 +441,7 @@
     public void unregisterProjectionStatusListener(ICarProjectionStatusListener listener)
             throws RemoteException {
         ICarImpl.assertProjectionStatusPermission(mContext);
-        mProjectionStatusListeners.remove(listener);
+        mProjectionStatusListeners.removeBinder(listener);
     }
 
     private ProjectionReceiverClient getOrCreateProjectionReceiverClientLocked(
@@ -488,8 +488,14 @@
         }
 
         if (singleListenerToNotify == null) {
-            for (ICarProjectionStatusListener listener : mProjectionStatusListeners) {
-                listener.onProjectionStatusChanged(currentState, currentPackage, statuses);
+            for (BinderInterface<ICarProjectionStatusListener> listener :
+                    mProjectionStatusListeners.getInterfaces()) {
+                try {
+                    listener.binderInterface.onProjectionStatusChanged(
+                            currentState, currentPackage, statuses);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Error calling to projection status listener", ex);
+                }
             }
         } else {
             singleListenerToNotify.onProjectionStatusChanged(
@@ -793,6 +799,8 @@
             writer.println("Current projection state: " + mCurrentProjectionState);
             writer.println("Current projection package: " + mCurrentProjectionPackage);
             writer.println("Projection status: " + mProjectionReceiverClients);
+            writer.println("Projection status listeners: "
+                    + mProjectionStatusListeners.getInterfaces());
             writer.println("WifiScanner: " + mWifiScanner);
         }
     }