Change isRinging and isInAPhoneCall to execute from binder thread.

We call into the audio service from telecomm main thread through
setMode, but it calls us back on isInAPhoneCall which tries to move
the code execution to the main thread (where it waiting for
audio service) causing a deadlock.  Change isInAPhoneCall() to support
multi-threaded execution and do not force the invocation onto the
main thread.

Bug: 16179606
Change-Id: I2cc6f6220b34a2b35841a08897a50f2dc50839c6
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index 3811de1..99731d7 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -33,6 +33,7 @@
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 /**
  * Singleton.
@@ -72,7 +73,7 @@
      * The main call repository. Keeps an instance of all live calls. New incoming and outgoing
      * calls are added to the map and removed when the calls move to the disconnected state.
      */
-    private final Set<Call> mCalls = new LinkedHashSet<>();
+    private final Set<Call> mCalls = new CopyOnWriteArraySet<Call>();
 
     private final DtmfLocalTonePlayer mDtmfLocalTonePlayer = new DtmfLocalTonePlayer();
     private final InCallController mInCallController = new InCallController();
diff --git a/src/com/android/telecomm/TelecommServiceImpl.java b/src/com/android/telecomm/TelecommServiceImpl.java
index 9aa4687..f1ab6c0 100644
--- a/src/com/android/telecomm/TelecommServiceImpl.java
+++ b/src/com/android/telecomm/TelecommServiceImpl.java
@@ -68,12 +68,6 @@
                     case MSG_SHOW_CALL_SCREEN:
                         mCallsManager.getInCallController().bringToForeground(msg.arg1 == 1);
                         break;
-                    case MSG_IS_IN_A_PHONE_CALL:
-                        result = mCallsManager.hasAnyCalls();
-                        break;
-                    case MSG_IS_RINGING:
-                        result = mCallsManager.hasRingingCall();
-                        break;
                     case MSG_END_CALL:
                         result = endCallInternal();
                         break;
@@ -102,11 +96,9 @@
 
     private static final int MSG_SILENCE_RINGER = 1;
     private static final int MSG_SHOW_CALL_SCREEN = 2;
-    private static final int MSG_IS_IN_A_PHONE_CALL = 3;
-    private static final int MSG_IS_RINGING = 4;
-    private static final int MSG_END_CALL = 5;
-    private static final int MSG_ACCEPT_RINGING_CALL = 6;
-    private static final int MSG_CANCEL_MISSED_CALLS_NOTIFICATION = 7;
+    private static final int MSG_END_CALL = 3;
+    private static final int MSG_ACCEPT_RINGING_CALL = 4;
+    private static final int MSG_CANCEL_MISSED_CALLS_NOTIFICATION = 5;
 
     /** The singleton instance. */
     private static TelecommServiceImpl sInstance;
@@ -226,7 +218,9 @@
     @Override
     public boolean isInAPhoneCall() {
         enforceReadPermission();
-        return (boolean) sendRequest(MSG_IS_IN_A_PHONE_CALL);
+        // Do not use sendRequest() with this method since it could cause a deadlock with
+        // audio service, which we call into from the main thread: AudioManager.setMode().
+        return mCallsManager.hasAnyCalls();
     }
 
     /**
@@ -235,7 +229,7 @@
     @Override
     public boolean isRinging() {
         enforceReadPermission();
-        return (boolean) sendRequest(MSG_IS_RINGING);
+        return mCallsManager.hasRingingCall();
     }
 
     /**