Merge "Updating APIs for CDMA conference call support." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index dfba909..a1f4bc2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28231,17 +28231,19 @@
 
   public abstract class Conference {
     ctor public Conference(android.telecomm.PhoneAccountHandle);
-    method public boolean addConnection(android.telecomm.Connection);
-    method public void destroy();
+    method public final boolean addConnection(android.telecomm.Connection);
+    method public final void destroy();
     method public final int getCapabilities();
     method public final java.util.List<android.telecomm.Connection> getConnections();
     method public final android.telecomm.PhoneAccountHandle getPhoneAccount();
     method public final int getState();
     method public void onDisconnect();
     method public void onHold();
+    method public void onMerge();
     method public void onSeparate(android.telecomm.Connection);
+    method public void onSwap();
     method public void onUnhold();
-    method public void removeConnection(android.telecomm.Connection);
+    method public final void removeConnection(android.telecomm.Connection);
     method public final void setActive();
     method public final void setCapabilities(int);
     method public final void setDisconnected(int, java.lang.String);
@@ -28392,13 +28394,13 @@
     method public static java.lang.String toString(int);
     field public static final int ADD_CALL = 16; // 0x10
     field public static final int ALL = 255; // 0xff
-    field public static final int GENERIC_CONFERENCE = 128; // 0x80
     field public static final int HOLD = 1; // 0x1
-    field public static final int MERGE_CALLS = 4; // 0x4
+    field public static final int MANAGE_CONFERENCE = 128; // 0x80
+    field public static final int MERGE_CONFERENCE = 4; // 0x4
     field public static final int MUTE = 64; // 0x40
     field public static final int RESPOND_VIA_TEXT = 32; // 0x20
     field public static final int SUPPORT_HOLD = 2; // 0x2
-    field public static final int SWAP_CALLS = 8; // 0x8
+    field public static final int SWAP_CONFERENCE = 8; // 0x8
   }
 
   public class PropertyPresentation {
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 5bf0855..c3aa2a0 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -517,6 +517,20 @@
     }
 
     /**
+     * Merges the calls within this conference. See {@link PhoneCapabilities#MERGE_CONFERENCE}.
+     */
+    public void mergeConference() {
+        mInCallAdapter.mergeConference(mTelecommCallId);
+    }
+
+    /**
+     * Swaps the calls within this conference. See {@link PhoneCapabilities#SWAP_CONFERENCE}.
+     */
+    public void swapConference() {
+        mInCallAdapter.swapConference(mTelecommCallId);
+    }
+
+    /**
      * Obtains the parent of this {@code Call} in a conference, if any.
      *
      * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index 879ff66..c838b48 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -93,6 +93,18 @@
     public void onUnhold() {}
 
     /**
+     * Invoked when the child calls should be merged. Only invoked if the conference contains the
+     * capability {@link PhoneCapabilities#MERGE_CONFERENCE}.
+     */
+    public void onMerge() {}
+
+    /**
+     * Invoked when the child calls should be swapped. Only invoked if the conference contains the
+     * capability {@link PhoneCapabilities#SWAP_CONFERENCE}.
+     */
+    public void onSwap() {}
+
+    /**
      * Sets state to be on hold.
      */
     public final void setOnHold() {
@@ -141,7 +153,7 @@
      * @param connection The connection to add.
      * @return True if the connection was successfully added.
      */
-    public boolean addConnection(Connection connection) {
+    public final boolean addConnection(Connection connection) {
         if (connection != null && !mChildConnections.contains(connection)) {
             if (connection.setConference(this)) {
                 mChildConnections.add(connection);
@@ -160,7 +172,7 @@
      * @param connection The connection to remove.
      * @return True if the connection was successfully removed.
      */
-    public void removeConnection(Connection connection) {
+    public final void removeConnection(Connection connection) {
         Log.d(this, "removing %s from %s", connection, mChildConnections);
         if (connection != null && mChildConnections.remove(connection)) {
             connection.resetConference();
@@ -173,7 +185,7 @@
     /**
      * Tears down the conference object and any of it's current connections.
      */
-    public void destroy() {
+    public final void destroy() {
         Log.d(this, "destroying conference : %s", this);
         // Tear down the children.
         for (Connection connection : mChildConnections) {
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 4d6e267..6df117e 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -1068,10 +1068,10 @@
         if (mState != state) {
             Log.d(this, "setState: %s", stateToString(state));
             mState = state;
+            onSetState(state);
             for (Listener l : mListeners) {
                 l.onStateChanged(this, state);
             }
-            onSetState(state);
         }
     }
 
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 2dc6910..833aa26 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -72,6 +72,8 @@
     private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 15;
     private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
     private static final int MSG_ANSWER_VIDEO = 17;
+    private static final int MSG_MERGE_CONFERENCE = 18;
+    private static final int MSG_SWAP_CONFERENCE = 19;
 
     private static Connection sNullConnection;
 
@@ -182,6 +184,16 @@
         }
 
         @Override
+        public void mergeConference(String callId) {
+            mHandler.obtainMessage(MSG_MERGE_CONFERENCE, callId).sendToTarget();
+        }
+
+        @Override
+        public void swapConference(String callId) {
+            mHandler.obtainMessage(MSG_SWAP_CONFERENCE, callId).sendToTarget();
+        }
+
+        @Override
         public void onPostDialContinue(String callId, boolean proceed) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
@@ -298,6 +310,12 @@
                 case MSG_SPLIT_FROM_CONFERENCE:
                     splitFromConference((String) msg.obj);
                     break;
+                case MSG_MERGE_CONFERENCE:
+                    mergeConference((String) msg.obj);
+                    break;
+                case MSG_SWAP_CONFERENCE:
+                    swapConference((String) msg.obj);
+                    break;
                 case MSG_ON_POST_DIAL_CONTINUE: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
@@ -639,6 +657,22 @@
         }
     }
 
+    private void mergeConference(String callId) {
+        Log.d(this, "mergeConference(%s)", callId);
+        Conference conference = findConferenceForAction(callId, "mergeConference");
+        if (conference != null) {
+            conference.onMerge();
+        }
+    }
+
+    private void swapConference(String callId) {
+        Log.d(this, "swapConference(%s)", callId);
+        Conference conference = findConferenceForAction(callId, "swapConference");
+        if (conference != null) {
+            conference.onSwap();
+        }
+    }
+
     private void onPostDialContinue(String callId, boolean proceed) {
         Log.d(this, "onPostDialContinue(%s)", callId);
         findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index 80f7b57..96ea5a6 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -241,6 +241,26 @@
     }
 
     /**
+     * Instructs Telecomm to merge child calls of the specified conference call.
+     */
+    public void mergeConference(String callId) {
+        try {
+            mAdapter.mergeConference(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Instructs Telecomm to swap the child calls of the specified conference call.
+     */
+    public void swapConference(String callId) {
+        try {
+            mAdapter.swapConference(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
      * Instructs Telecomm to turn the proximity sensor on.
      */
     public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecomm/PhoneCapabilities.java b/telecomm/java/android/telecomm/PhoneCapabilities.java
index 3d76608..7a338b4 100644
--- a/telecomm/java/android/telecomm/PhoneCapabilities.java
+++ b/telecomm/java/android/telecomm/PhoneCapabilities.java
@@ -27,11 +27,17 @@
     /** Call supports the hold feature. */
     public static final int SUPPORT_HOLD       = 0x00000002;
 
-    /** Call can currently be merged. */
-    public static final int MERGE_CALLS        = 0x00000004;
+    /**
+     * Calls within a conference can be merged. Some connection services create a conference call
+     * only after two calls have been merged.  However, a conference call can also be added the
+     * moment there are more than one call. CDMA calls are implemented in this way because the call
+     * actions are more limited when more than one call exists. This flag allows merge to be exposed
+     * as a capability on the conference call instead of individual calls.
+     */
+    public static final int MERGE_CONFERENCE   = 0x00000004;
 
-    /** Call can currently be swapped with another call. */
-    public static final int SWAP_CALLS         = 0x00000008;
+    /** Calls withing a conference can be swapped between foreground and background. */
+    public static final int SWAP_CONFERENCE    = 0x00000008;
 
     /** Call currently supports adding another call to this one. */
     public static final int ADD_CALL           = 0x00000010;
@@ -42,8 +48,11 @@
     /** Call can be muted. */
     public static final int MUTE               = 0x00000040;
 
-    /** Call supports generic conference mode. */
-    public static final int GENERIC_CONFERENCE = 0x00000080;
+    /**
+     * Call supports conference call management. This capability only applies to conference calls
+     * which can have other calls as children.
+     */
+    public static final int MANAGE_CONFERENCE = 0x00000080;
 
     /**
      * Local device supports video telephony.
@@ -69,8 +78,8 @@
      */
     public static final int VoWIFI = 0x00000800;
 
-    public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CALLS | SWAP_CALLS | ADD_CALL
-            | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE;
+    public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CONFERENCE | SWAP_CONFERENCE | ADD_CALL
+            | RESPOND_VIA_TEXT | MUTE | MANAGE_CONFERENCE;
 
     public static String toString(int capabilities) {
         StringBuilder builder = new StringBuilder();
@@ -81,11 +90,11 @@
         if ((capabilities & SUPPORT_HOLD) != 0) {
             builder.append(" SUPPORT_HOLD");
         }
-        if ((capabilities & MERGE_CALLS) != 0) {
-            builder.append(" MERGE_CALLS");
+        if ((capabilities & MERGE_CONFERENCE) != 0) {
+            builder.append(" MERGE_CONFERENCE");
         }
-        if ((capabilities & SWAP_CALLS) != 0) {
-            builder.append(" SWAP_CALLS");
+        if ((capabilities & SWAP_CONFERENCE) != 0) {
+            builder.append(" SWAP_CONFERENCE");
         }
         if ((capabilities & ADD_CALL) != 0) {
             builder.append(" ADD_CALL");
@@ -96,8 +105,8 @@
         if ((capabilities & MUTE) != 0) {
             builder.append(" MUTE");
         }
-        if ((capabilities & GENERIC_CONFERENCE) != 0) {
-            builder.append(" GENERIC_CONFERENCE");
+        if ((capabilities & MANAGE_CONFERENCE) != 0) {
+            builder.append(" MANAGE_CONFERENCE");
         }
         if ((capabilities & SUPPORTS_VT_LOCAL) != 0) {
             builder.append(" SUPPORTS_VT_LOCAL");
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
index 32b877d..a673733 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
@@ -65,6 +65,10 @@
 
     void splitFromConference(String callId);
 
+    void mergeConference(String conferenceCallId);
+
+    void swapConference(String conferenceCallId);
+
     void onPostDialContinue(String callId, boolean proceed);
 
     void onPhoneAccountClicked(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index 2ce5c6b..626bb91 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -54,6 +54,10 @@
 
     void splitFromConference(String callId);
 
+    void mergeConference(String callId);
+
+    void swapConference(String callId);
+
     void turnOnProximitySensor();
 
     void turnOffProximitySensor(boolean screenOnImmediately);