Merge "Show error message for RuntimeExceptions." into mnc-dev
diff --git a/src/com/android/services/telephony/ConferenceParticipantConnection.java b/src/com/android/services/telephony/ConferenceParticipantConnection.java
index eae3696..c142cc3 100644
--- a/src/com/android/services/telephony/ConferenceParticipantConnection.java
+++ b/src/com/android/services/telephony/ConferenceParticipantConnection.java
@@ -29,6 +29,11 @@
 public class ConferenceParticipantConnection extends Connection {
 
     /**
+     * The user entity URI For the conference participant.
+     */
+    private final Uri mUserEntity;
+
+    /**
      * The endpoint URI For the conference participant.
      */
     private final Uri mEndpoint;
@@ -51,6 +56,7 @@
         setAddress(participant.getHandle(), PhoneConstants.PRESENTATION_ALLOWED);
         setCallerDisplayName(participant.getDisplayName(), PhoneConstants.PRESENTATION_ALLOWED);
 
+        mUserEntity = participant.getHandle();
         mEndpoint = participant.getEndpoint();
         setCapabilities();
     }
@@ -102,7 +108,16 @@
      */
     @Override
     public void onDisconnect() {
-        mParentConnection.onDisconnectConferenceParticipant(mEndpoint);
+        mParentConnection.onDisconnectConferenceParticipant(mUserEntity);
+    }
+
+    /**
+     * Retrieves the user handle for this connection.
+     *
+     * @return The userEntity.
+     */
+    public Uri getUserEntity() {
+        return mUserEntity;
     }
 
     /**
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 682326f..b0785d4 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -147,7 +147,7 @@
         public void onConferenceParticipantsChanged(android.telecom.Connection c,
                 List<ConferenceParticipant> participants) {
 
-            if (c == null) {
+            if (c == null || participants == null) {
                 return;
             }
             Log.v(this, "onConferenceParticipantsChanged: %d participants", participants.size());
@@ -203,6 +203,16 @@
             mConferenceParticipantConnections =
                     new ConcurrentHashMap<Uri, ConferenceParticipantConnection>(8, 0.9f, 1);
 
+    public void updateConferenceParticipantsAfterCreation() {
+        if (mConferenceHost != null) {
+            Log.v(this, "updateConferenceStateAfterCreation :: process participant update");
+            handleConferenceParticipantsUpdate(mConferenceHost,
+                    mConferenceHost.getConferenceParticipants());
+        } else {
+            Log.v(this, "updateConferenceStateAfterCreation :: null mConferenceHost");
+        }
+    }
+
     /**
      * Initializes a new {@link ImsConference}.
      *
@@ -487,22 +497,26 @@
     private void handleConferenceParticipantsUpdate(
             TelephonyConnection parent, List<ConferenceParticipant> participants) {
 
+        if (participants == null) {
+            return;
+        }
         boolean newParticipantsAdded = false;
         boolean oldParticipantsRemoved = false;
         ArrayList<ConferenceParticipant> newParticipants = new ArrayList<>(participants.size());
-        HashSet<Uri> participantEndpoints = new HashSet<>(participants.size());
+        HashSet<Uri> participantUserEntities = new HashSet<>(participants.size());
 
         // Add any new participants and update existing.
         for (ConferenceParticipant participant : participants) {
-            Uri endpoint = participant.getEndpoint();
-            participantEndpoints.add(endpoint);
-            if (!mConferenceParticipantConnections.containsKey(endpoint)) {
+            Uri userEntity = participant.getHandle();
+
+            participantUserEntities.add(userEntity);
+            if (!mConferenceParticipantConnections.containsKey(userEntity)) {
                 createConferenceParticipantConnection(parent, participant);
                 newParticipants.add(participant);
                 newParticipantsAdded = true;
             } else {
                 ConferenceParticipantConnection connection =
-                        mConferenceParticipantConnections.get(endpoint);
+                        mConferenceParticipantConnections.get(userEntity);
                 connection.updateState(participant.getState());
             }
         }
@@ -512,7 +526,7 @@
             // Set the state of the new participants at once and add to the conference
             for (ConferenceParticipant newParticipant : newParticipants) {
                 ConferenceParticipantConnection connection =
-                        mConferenceParticipantConnections.get(newParticipant.getEndpoint());
+                        mConferenceParticipantConnections.get(newParticipant.getHandle());
                 connection.updateState(newParticipant.getState());
             }
         }
@@ -524,9 +538,11 @@
         while (entryIterator.hasNext()) {
             Map.Entry<Uri, ConferenceParticipantConnection> entry = entryIterator.next();
 
-            if (!participantEndpoints.contains(entry.getKey())) {
+            if (!participantUserEntities.contains(entry.getKey())) {
                 ConferenceParticipantConnection participant = entry.getValue();
+                participant.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
                 participant.removeConnectionListener(mParticipantListener);
+                mTelephonyConnectionService.removeConnection(participant);
                 removeConnection(participant);
                 entryIterator.remove();
                 oldParticipantsRemoved = true;
@@ -563,7 +579,7 @@
             Log.v(this, "createConferenceParticipantConnection: %s", connection);
         }
 
-        mConferenceParticipantConnections.put(participant.getEndpoint(), connection);
+        mConferenceParticipantConnections.put(participant.getHandle(), connection);
         PhoneAccountHandle phoneAccountHandle =
                 PhoneUtils.makePstnPhoneAccountHandle(parent.getPhone());
         mTelephonyConnectionService.addExistingConnection(phoneAccountHandle, connection);
@@ -576,12 +592,10 @@
      * @param participant The participant to remove.
      */
     private void removeConferenceParticipant(ConferenceParticipantConnection participant) {
-        if (Log.VERBOSE) {
-            Log.v(this, "removeConferenceParticipant: %s", participant);
-        }
+        Log.d(this, "removeConferenceParticipant: %s", participant);
 
         participant.removeConnectionListener(mParticipantListener);
-        mConferenceParticipantConnections.remove(participant.getEndpoint());
+        mConferenceParticipantConnections.remove(participant.getUserEntity());
     }
 
     /**
@@ -597,6 +611,7 @@
             // Mark disconnect cause as cancelled to ensure that the call is not logged in the
             // call log.
             connection.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
+            mTelephonyConnectionService.removeConnection(connection);
             connection.destroy();
         }
         mConferenceParticipantConnections.clear();
@@ -651,9 +666,11 @@
             case Connection.STATE_INITIALIZING:
             case Connection.STATE_NEW:
             case Connection.STATE_RINGING:
-            case Connection.STATE_DIALING:
                 // No-op -- not applicable.
                 break;
+            case Connection.STATE_DIALING:
+                setDialing();
+                break;
             case Connection.STATE_DISCONNECTED:
                 DisconnectCause disconnectCause;
                 if (mConferenceHost == null) {
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index b266b81..f445dcb 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -318,8 +318,9 @@
         // Create conference and add to telecom
         ImsConference conference = new ImsConference(mConnectionService, conferenceHostConnection);
         conference.setState(connection.getState());
-        mConnectionService.addConference(conference);
         conference.addListener(mConferenceListener);
+        conference.updateConferenceParticipantsAfterCreation();
+        mConnectionService.addConference(conference);
 
         // Cleanup TelephonyConnection which backed the original connection and remove from telecom.
         // Use the "Other" disconnect cause to ensure the call is logged to the call log but the
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index fa3c506..b5610e5 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -74,6 +74,7 @@
                         Log.d(TelephonyConnection.this, "SettingOriginalConnection " +
                                 mOriginalConnection.toString() + " with " + connection.toString());
                         setOriginalConnection(connection);
+                        mWasImsConnection = false;
                     }
                     break;
                 case MSG_RINGBACK_TONE:
@@ -657,6 +658,18 @@
         return null;
     }
 
+     /**
+     * Checks for and returns the list of conference participants
+     * associated with this connection.
+     */
+    public List<ConferenceParticipant> getConferenceParticipants() {
+        if (mOriginalConnection == null) {
+            Log.v(this, "Null mOriginalConnection, cannot get conf participants.");
+            return null;
+        }
+        return mOriginalConnection.getConferenceParticipants();
+    }
+
     /**
      * Checks to see the original connection corresponds to an active incoming call. Returns false
      * if there is no such actual call, or if the associated call is not incoming (See