am c242f857: Merge "IMS SRVCC handling and call log cleanup." into lmp-mr1-dev

* commit 'c242f8573f719af3b402f6a304ca957f675e3600':
  IMS SRVCC handling and call log cleanup.
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 0d235c3..5fc3e41 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -19,6 +19,7 @@
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 
 import android.net.Uri;
 import android.telecom.Connection;
@@ -84,6 +85,21 @@
     };
 
     /**
+     * Listener used to respond to changes to the underlying radio connection for the conference
+     * host connection.  Used to respond to SRVCC changes.
+     */
+    private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
+            new TelephonyConnection.TelephonyConnectionListener() {
+
+        @Override
+        public void onOriginalConnectionConfigured(TelephonyConnection c) {
+            if (c == mConferenceHost) {
+               handleOriginalConnectionChange();
+            }
+        }
+    };
+
+    /**
      * Listener used to respond to changes to the connection to the IMS conference server.
      */
     private final android.telecom.Connection.Listener mConferenceHostListener =
@@ -202,6 +218,9 @@
     @Override
     public void onDisconnect() {
         Log.v(this, "onDisconnect: hanging up conference host.");
+        if (mConferenceHost == null) {
+            return;
+        }
 
         Call call = mConferenceHost.getCall();
         if (call != null) {
@@ -249,6 +268,9 @@
      */
     @Override
     public void onHold() {
+        if (mConferenceHost == null) {
+            return;
+        }
         mConferenceHost.performHold();
     }
 
@@ -257,6 +279,9 @@
      */
     @Override
     public void onUnhold() {
+        if (mConferenceHost == null) {
+            return;
+        }
         mConferenceHost.performUnhold();
     }
 
@@ -267,7 +292,10 @@
      */
     @Override
     public void onPlayDtmfTone(char c) {
-         mConferenceHost.onPlayDtmfTone(c);
+        if (mConferenceHost == null) {
+            return;
+        }
+        mConferenceHost.onPlayDtmfTone(c);
     }
 
     /**
@@ -275,6 +303,9 @@
      */
     @Override
     public void onStopDtmfTone() {
+        if (mConferenceHost == null) {
+            return;
+        }
         mConferenceHost.onStopDtmfTone();
     }
 
@@ -326,6 +357,7 @@
 
         mConferenceHost = new ConferenceHostConnection(conferenceHost);
         mConferenceHost.addConnectionListener(mConferenceHostListener);
+        mConferenceHost.addTelephonyConnectionListener(mTelephonyConnectionListener);
     }
 
     /**
@@ -455,6 +487,41 @@
     }
 
     /**
+     * Handles a change in the original connection backing the conference host connection.  This can
+     * happen if an SRVCC event occurs on the original IMS connection, requiring a fallback to
+     * GSM or CDMA.
+     * <p>
+     * If this happens, we will add the conference host connection to telecom and tear down the
+     * conference.
+     */
+    private void handleOriginalConnectionChange() {
+        if (mConferenceHost == null) {
+            Log.w(this, "handleOriginalConnectionChange; conference host missing.");
+            return;
+        }
+
+        com.android.internal.telephony.Connection originalConnection =
+                mConferenceHost.getOriginalConnection();
+
+        if (!(originalConnection instanceof ImsPhoneConnection)) {
+            if (Log.VERBOSE) {
+                Log.v(this,
+                        "Original connection for conference host is no longer an IMS connection; " +
+                                "new connection: %s", originalConnection);
+            }
+
+            PhoneAccountHandle phoneAccountHandle =
+                    TelecomAccountRegistry.makePstnPhoneAccountHandle(mConferenceHost.getPhone());
+            mTelephonyConnectionService.addExistingConnection(phoneAccountHandle, mConferenceHost);
+            mConferenceHost.removeConnectionListener(mConferenceHostListener);
+            mConferenceHost.removeTelephonyConnectionListener(mTelephonyConnectionListener);
+            mConferenceHost = null;
+            setDisconnected(new DisconnectCause(DisconnectCause.OTHER));
+            destroy();
+        }
+    }
+
+    /**
      * Changes the state of the Ims conference.
      *
      * @param state the new state.
@@ -470,8 +537,14 @@
                 // No-op -- not applicable.
                 break;
             case Connection.STATE_DISCONNECTED:
-                setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
-                        mConferenceHost.getOriginalConnection().getDisconnectCause()));
+                DisconnectCause disconnectCause;
+                if (mConferenceHost == null) {
+                    disconnectCause = new DisconnectCause(DisconnectCause.CANCELED);
+                } else {
+                    disconnectCause = DisconnectCauseUtil.toTelecomDisconnectCause(
+                            mConferenceHost.getOriginalConnection().getDisconnectCause());
+                }
+                setDisconnected(disconnectCause);
                 destroy();
                 break;
             case Connection.STATE_ACTIVE:
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 6d92fbb..e924687 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -264,10 +264,11 @@
         conference.addListener(mConferenceListener);
 
         // Cleanup TelephonyConnection which backed the original connection and remove from telecom.
-        // Use the "Canceled" disconnect cause to ensure the call is not logged.
+        // Use the "Other" disconnect cause to ensure the call is logged to the call log but the
+        // disconnect tone is not played.
         connection.removeConnectionListener(mConnectionListener);
         connection.clearOriginalConnection();
-        connection.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
+        connection.setDisconnected(new DisconnectCause(DisconnectCause.OTHER));
         connection.destroy();
         mImsConferences.add(conference);
     }