Prevent merging conference calls hosted on peer device.

With IMS, the "multiparty" bit on an ImsCall is set to "true" when a call
is merged into a conference.  This not only occurs on the device hosting
the conference call, but also on the devices of the callers merged into
the conference.

This CL adds code to propagate changes in the multiparty state of a call
from the ImsCall up to the ImsPhoneConnection.

Bug: 19478784
Change-Id: I51b84731dbc77a235d2602db751af016e6c397ea
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
index 04c4a89..f6898d0 100644
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -50,6 +50,7 @@
                 android.telecom.Connection.VideoProvider videoProvider);
         public void onAudioQualityChanged(int audioQuality);
         public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants);
+        public void onMultipartyStateChanged(boolean isMultiParty);
     }
 
     /**
@@ -71,6 +72,8 @@
         public void onAudioQualityChanged(int audioQuality) {}
         @Override
         public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {}
+        @Override
+        public void onMultipartyStateChanged(boolean isMultiParty) {}
     }
 
     public static final int AUDIO_QUALITY_STANDARD = 1;
@@ -609,6 +612,17 @@
     }
 
     /**
+     * Notifies listeners of a change to the multiparty state of the connection..
+     *
+     * @param isMultiparty The participant(s).
+     */
+    public void updateMultipartyState(boolean isMultiparty) {
+        for (Listener l : mListeners) {
+            l.onMultipartyStateChanged(isMultiparty);
+        }
+    }
+
+    /**
      * Notifies this Connection of a request to disconnect a participant of the conference managed
      * by the connection.
      *
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 5324111..8f28921 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -1221,6 +1221,24 @@
                     ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" + reasonInfo);
             }
         }
+
+        /**
+         * Handles a change to the multiparty state for an {@code ImsCall}.  Notifies the associated
+         * {@link ImsPhoneConnection} of the change.
+         *
+         * @param imsCall The IMS call.
+         * @param isMultiParty {@code true} if the call became multiparty, {@code false}
+         *      otherwise.
+         */
+        @Override
+        public void onMultipartyStateChanged(ImsCall imsCall, boolean isMultiParty) {
+            if (DBG) log("onMultipartyStateChanged to " + (isMultiParty ? "Y" : "N"));
+
+            ImsPhoneConnection conn = findConnection(imsCall);
+            if (conn != null) {
+                conn.updateMultipartyState(isMultiParty);
+            }
+        }
     };
 
     /**
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
index f83aba0..b592485 100755
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -131,7 +131,6 @@
                     imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_OIR));
             mCnapNamePresentation = ImsCallProfile.OIRToPresentation(
                     imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
-
             updateMediaCapabilities(imsCall);
         } else {
             mNumberPresentation = PhoneConstants.PRESENTATION_UNKNOWN;
@@ -537,6 +536,21 @@
         return mImsCall != null && mImsCall.isMultiparty();
     }
 
+    /**
+     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
+     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
+     * {@link ImsCall} is a member of a conference hosted on another device.
+     *
+     * @return {@code true} if this call is the origin of the conference call it is a member of,
+     *      {@code false} otherwise.
+     */
+    public boolean isConferenceHost() {
+        if (mImsCall == null) {
+            return false;
+        }
+        return mImsCall.isConferenceHost();
+    }
+
     /*package*/ ImsCall getImsCall() {
         return mImsCall;
     }
@@ -575,6 +589,7 @@
         boolean updateParent = mParent.update(this, imsCall, state);
         boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
         boolean updateWifiState = updateWifiState();
+
         return updateParent || updateMediaCapabilities || updateWifiState;
     }