Fix problem where incoming calls would hang and never complete

Bug: 19941246
Change-Id: I50f50f2ab81a79069a5a7a0884eaa75daa43a909
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 9e29fe1..f5f9606 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -22,6 +22,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Trace;
 import android.provider.ContactsContract.Contacts;
 import android.telecom.CallState;
@@ -175,7 +176,9 @@
     private final Runnable mDirectToVoicemailRunnable = new Runnable() {
         @Override
         public void run() {
-            processDirectToVoicemail();
+            synchronized (mLock) {
+                processDirectToVoicemail();
+            }
         }
     };
 
@@ -209,7 +212,7 @@
 
     private PhoneAccountHandle mTargetPhoneAccountHandle;
 
-    private final Handler mHandler = new Handler();
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
 
     private final List<Call> mConferenceableCalls = new ArrayList<>();
 
@@ -303,6 +306,7 @@
     private final ContactsAsyncHelper mContactsAsyncHelper;
     private final Context mContext;
     private final CallsManager mCallsManager;
+    private final TelecomSystem.SyncRoot mLock;
 
     private boolean mWasConferencePreviouslyMerged = false;
 
@@ -331,6 +335,7 @@
     public Call(
             Context context,
             CallsManager callsManager,
+            TelecomSystem.SyncRoot lock,
             ConnectionServiceRepository repository,
             ContactsAsyncHelper contactsAsyncHelper,
             Uri handle,
@@ -342,6 +347,7 @@
         mState = isConference ? CallState.ACTIVE : CallState.NEW;
         mContext = context;
         mCallsManager = callsManager;
+        mLock = lock;
         mRepository = repository;
         mContactsAsyncHelper = contactsAsyncHelper;
         setHandle(handle);
@@ -372,6 +378,7 @@
     Call(
             Context context,
             CallsManager callsManager,
+            TelecomSystem.SyncRoot lock,
             ConnectionServiceRepository repository,
             ContactsAsyncHelper contactsAsyncHelper,
             Uri handle,
@@ -381,7 +388,7 @@
             boolean isIncoming,
             boolean isConference,
             long connectTimeMillis) {
-        this(context, callsManager, repository, contactsAsyncHelper, handle, gatewayInfo,
+        this(context, callsManager, lock, repository, contactsAsyncHelper, handle, gatewayInfo,
                 connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, isIncoming,
                 isConference);
 
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 8d1144d..037dd66 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.media.AudioManager;
+import android.os.Binder;
 import android.telecom.AudioState;
 import android.telecom.CallState;
 
@@ -418,8 +419,13 @@
         // it a hint about the purpose of our focus.
         if (mAudioFocusStreamType != stream) {
             Log.v(this, "requesting audio focus for stream: %d", stream);
-            mAudioManager.requestAudioFocusForCall(stream,
-                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+            long token = Binder.clearCallingIdentity();
+            try {
+                mAudioManager.requestAudioFocusForCall(stream,
+                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
         mAudioFocusStreamType = stream;
 
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index aaa075a..52dd55d 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -20,6 +20,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Trace;
 import android.provider.CallLog.Calls;
 import android.telecom.AudioState;
@@ -127,7 +128,7 @@
     private final Set<Call> mLocallyDisconnectingCalls = new HashSet<>();
     private final Set<Call> mPendingCallsToDisconnect = new HashSet<>();
     /* Handler tied to thread in which CallManager was initialized. */
-    private final Handler mHandler = new Handler();
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
 
     private boolean mCanAddCall = true;
 
@@ -429,6 +430,7 @@
         Call call = new Call(
                 mContext,
                 this,
+                mLock,
                 mConnectionServiceRepository,
                 mContactsAsyncHelper,
                 handle,
@@ -450,6 +452,7 @@
         Call call = new Call(
                 mContext,
                 this,
+                mLock,
                 mConnectionServiceRepository,
                 mContactsAsyncHelper,
                 handle,
@@ -488,6 +491,7 @@
         return new Call(
                 mContext,
                 this,
+                mLock,
                 mConnectionServiceRepository,
                 mContactsAsyncHelper,
                 handle,
@@ -1071,6 +1075,7 @@
         Call call = new Call(
                 mContext,
                 this,
+                mLock,
                 mConnectionServiceRepository,
                 mContactsAsyncHelper,
                 null /* handle */,
@@ -1419,6 +1424,7 @@
         Call call = new Call(
                 mContext,
                 this,
+                mLock,
                 mConnectionServiceRepository,
                 mContactsAsyncHelper,
                 connection.getHandle() /* handle */,
diff --git a/src/com/android/server/telecom/CreateConnectionTimeout.java b/src/com/android/server/telecom/CreateConnectionTimeout.java
index 3f308cc..1878177 100644
--- a/src/com/android/server/telecom/CreateConnectionTimeout.java
+++ b/src/com/android/server/telecom/CreateConnectionTimeout.java
@@ -20,6 +20,7 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.os.Handler;
+import android.os.Looper;
 import android.telecom.CallState;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.TelephonyManager;
@@ -37,7 +38,7 @@
     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final ConnectionServiceWrapper mConnectionService;
     private final Call mCall;
-    private final Handler mHandler = new Handler();
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
     private boolean mIsRegistered;
     private boolean mIsCallTimedOut;
 
diff --git a/src/com/android/server/telecom/RespondViaSmsManager.java b/src/com/android/server/telecom/RespondViaSmsManager.java
index 98ba3b4..e5a2042 100644
--- a/src/com/android/server/telecom/RespondViaSmsManager.java
+++ b/src/com/android/server/telecom/RespondViaSmsManager.java
@@ -28,6 +28,7 @@
 import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.telecom.Response;
 import android.telephony.SubscriptionManager;
@@ -46,7 +47,7 @@
     private final CallsManager mCallsManager;
     private final TelecomSystem.SyncRoot mLock;
 
-    private final Handler mHandler = new Handler() {
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
diff --git a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
index d26f4c5..bb1faed 100644
--- a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
+++ b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
@@ -339,7 +339,7 @@
                             synchronized (lock) {
 
                                 // Convert the data to a call object
-                                Call call = new Call(mContext, callsManager,
+                                Call call = new Call(mContext, callsManager, lock,
                                         null, contactsAsyncHelper, null, null, null, null, true,
                                         false);
                                 call.setDisconnectCause(