Catch exceptions in SipPhone.canTake().

Exceptions may throw during canTake() as the peer may cancel the call and
result in a race with this method call.

Change-Id: I61903d601d8f9b2dcb4c4fbe1586e2c1a1069109
http://b/issue?id=3033868
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 94307e6..af3e0886 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -126,14 +126,27 @@
                 return false;
             }
 
-            SipAudioCall sipAudioCall = (SipAudioCall) incomingCall;
-            Log.v(LOG_TAG, "  ++++++ taking call from: "
-                    + sipAudioCall.getPeerProfile().getUriString());
-            String localUri = sipAudioCall.getLocalProfile().getUriString();
-            if (localUri.equals(mProfile.getUriString())) {
-                boolean makeCallWait = foregroundCall.getState().isAlive();
-                ringingCall.initIncomingCall(sipAudioCall, makeCallWait);
-                return true;
+            try {
+                SipAudioCall sipAudioCall = (SipAudioCall) incomingCall;
+                Log.d(LOG_TAG, "+++ taking call from: "
+                        + sipAudioCall.getPeerProfile().getUriString());
+                String localUri = sipAudioCall.getLocalProfile().getUriString();
+                if (localUri.equals(mProfile.getUriString())) {
+                    boolean makeCallWait = foregroundCall.getState().isAlive();
+                    ringingCall.initIncomingCall(sipAudioCall, makeCallWait);
+                    if (sipAudioCall.getState()
+                            != SipSession.State.INCOMING_CALL) {
+                        // Peer cancelled the call!
+                        Log.d(LOG_TAG, "    call cancelled !!");
+                        ringingCall.reset();
+                    }
+                    return true;
+                }
+            } catch (Exception e) {
+                // Peer may cancel the call at any time during the time we hook
+                // up ringingCall with sipAudioCall. Clean up ringingCall when
+                // that happens.
+                ringingCall.reset();
             }
             return false;
         }
@@ -358,6 +371,11 @@
     }
 
     private class SipCall extends SipCallBase {
+        void reset() {
+            connections.clear();
+            setState(Call.State.IDLE);
+        }
+
         void switchWith(SipCall that) {
             synchronized (SipPhone.class) {
                 SipCall tmp = new SipCall();