Update telecomm to use new Conference call APIs.

Bug:16844332
Bug:16449372
Change-Id: I897df73b3e552c498ef36211e03970db7e0d303e
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index e2dbb79..7d694de 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -73,8 +73,6 @@
         void onRequestingRingback(Call call, boolean requestingRingback);
         void onPostDialWait(Call call, String remaining);
         void onCallCapabilitiesChanged(Call call);
-        void onExpiredConferenceCall(Call call);
-        void onConfirmedConferenceCall(Call call);
         void onParentChanged(Call call);
         void onChildrenChanged(Call call);
         void onCannedSmsResponsesLoaded(Call call);
@@ -110,10 +108,6 @@
         @Override
         public void onCallCapabilitiesChanged(Call call) {}
         @Override
-        public void onExpiredConferenceCall(Call call) {}
-        @Override
-        public void onConfirmedConferenceCall(Call call) {}
-        @Override
         public void onParentChanged(Call call) {}
         @Override
         public void onChildrenChanged(Call call) {}
@@ -346,15 +340,7 @@
     }
 
     int getState() {
-        if (mIsConference) {
-            if (!mChildCalls.isEmpty()) {
-                // If we have child calls, just return the child call.
-                return mChildCalls.get(0).getState();
-            }
-            return CallState.ACTIVE;
-        } else {
-            return mState;
-        }
+        return mState;
     }
 
     /**
@@ -855,27 +841,11 @@
         mConnectionService.onPhoneAccountClicked(this);
     }
 
-    void conferenceInto(Call conferenceCall) {
+    void conferenceWith(Call otherCall) {
         if (mConnectionService == null) {
             Log.w(this, "conference requested on a call without a connection service.");
         } else {
-            mConnectionService.conference(conferenceCall, this);
-        }
-    }
-
-    void expireConference() {
-        // The conference call expired before we got a confirmation of the conference from the
-        // connection service...so start shutting down.
-        clearConnectionService();
-        for (Listener l : mListeners) {
-            l.onExpiredConferenceCall(this);
-        }
-    }
-
-    void confirmConference() {
-        Log.v(this, "confirming Conf call %s", mListeners);
-        for (Listener l : mListeners) {
-            l.onConfirmedConferenceCall(this);
+            mConnectionService.conference(this, otherCall);
         }
     }
 
@@ -888,6 +858,10 @@
             Log.e(this, new Exception(), "setting the parent to self");
             return;
         }
+        if (parentCall == mParentCall) {
+            // nothing to do
+            return;
+        }
         Preconditions.checkState(parentCall == null || mParentCall == null);
 
         Call oldParent = mParentCall;
@@ -1214,7 +1188,7 @@
         }
     }
 
-    private int getStateFromConnectionState(int state) {
+    static int getStateFromConnectionState(int state) {
         switch (state) {
             case Connection.STATE_INITIALIZING:
                 return CallState.CONNECTING;
diff --git a/src/com/android/telecomm/CallIdMapper.java b/src/com/android/telecomm/CallIdMapper.java
index f5055da..b82d1e1 100644
--- a/src/com/android/telecomm/CallIdMapper.java
+++ b/src/com/android/telecomm/CallIdMapper.java
@@ -78,7 +78,7 @@
         if (objId instanceof String) {
             callId = (String) objId;
         }
-        if (!isValidCallId(callId)) {
+        if (!isValidCallId(callId) && !isValidConferenceId(callId)) {
             return null;
         }
 
@@ -94,6 +94,10 @@
         return callId != null && callId.startsWith(mCallIdPrefix);
     }
 
+    boolean isValidConferenceId(String callId) {
+        return callId != null;
+    }
+
     String getNewId() {
         sIdCount++;
         return mCallIdPrefix + sIdCount;
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index 314020d..d13d140 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -21,6 +21,7 @@
 import android.telecomm.AudioState;
 import android.telecomm.CallState;
 import android.telecomm.GatewayInfo;
+import android.telecomm.ParcelableConference;
 import android.telecomm.PhoneAccountHandle;
 import android.telephony.DisconnectCause;
 
@@ -188,20 +189,6 @@
     }
 
     @Override
-    public void onExpiredConferenceCall(Call call) {
-        call.removeListener(this);
-    }
-
-    @Override
-    public void onConfirmedConferenceCall(Call call) {
-        addCall(call);
-        Log.v(this, "confirming Conf call %s", call);
-        for (CallsManagerListener listener : mListeners) {
-            listener.onIsConferencedChanged(call);
-        }
-    }
-
-    @Override
     public void onParentChanged(Call call) {
         for (CallsManagerListener listener : mListeners) {
             listener.onIsConferencedChanged(call);
@@ -417,16 +404,7 @@
      * @param otherCall The other call to conference with.
      */
     void conference(Call call, Call otherCall) {
-        Call conferenceCall = new Call(
-                mConnectionServiceRepository,
-                null /* handle */,
-                null /* gatewayInfo */,
-                null /* connectionManagerPhoneAccount */,
-                null /* targetPhoneAccount */,
-                false /* isIncoming */,
-                true /* isConference */);
-        conferenceCall.addListener(this);
-        call.conferenceInto(conferenceCall);
+        call.conferenceWith(otherCall);
     }
 
     /**
@@ -751,6 +729,27 @@
         return null;
     }
 
+    Call createConferenceCall(
+            PhoneAccountHandle phoneAccount,
+            ParcelableConference parcelableConference) {
+        Call call = new Call(
+                mConnectionServiceRepository,
+                null /* handle */,
+                null /* gatewayInfo */,
+                null /* connectionManagerPhoneAccount */,
+                phoneAccount,
+                false /* isIncoming */,
+                true /* isConference */);
+
+        setCallState(call, Call.getStateFromConnectionState(parcelableConference.getState()));
+        call.setCallCapabilities(parcelableConference.getCapabilities());
+
+        // TODO: Move this to be a part of addCall()
+        call.addListener(this);
+        addCall(call);
+        return call;
+    }
+
     /**
      * Adds the specified call to the main list of live calls.
      *
diff --git a/src/com/android/telecomm/ConnectionServiceWrapper.java b/src/com/android/telecomm/ConnectionServiceWrapper.java
index 23ffab7..21f03e9 100644
--- a/src/com/android/telecomm/ConnectionServiceWrapper.java
+++ b/src/com/android/telecomm/ConnectionServiceWrapper.java
@@ -28,6 +28,8 @@
 import android.telecomm.ConnectionRequest;
 import android.telecomm.ConnectionService;
 import android.telecomm.GatewayInfo;
+
+import android.telecomm.ParcelableConference;
 import android.telecomm.ParcelableConnection;
 import android.telecomm.PhoneAccount;
 import android.telecomm.PhoneAccountHandle;
@@ -163,6 +165,7 @@
                         call = mCallIdMapper.getCall(args.arg1);
                         String disconnectMessage = (String) args.arg2;
                         int disconnectCause = args.argi1;
+                        Log.d(this, "disconnect call %s %s", args.arg1, call);
                         if (call != null) {
                             mCallsManager.markCallAsDisconnected(call, disconnectCause,
                                     disconnectMessage);
@@ -208,16 +211,11 @@
                         if (childCall != null) {
                             String conferenceCallId = (String) args.arg2;
                             if (conferenceCallId == null) {
+                                Log.d(this, "unsetting parent: %s", args.arg1);
                                 childCall.setParentCall(null);
                             } else {
                                 Call conferenceCall = mCallIdMapper.getCall(conferenceCallId);
-                                if (conferenceCall != null &&
-                                        !mPendingConferenceCalls.contains(conferenceCall)) {
-                                    childCall.setParentCall(conferenceCall);
-                                } else {
-                                    //Log.w(this, "setIsConferenced, unknown conference id %s",
-                                    //        conferenceCallId);
-                                }
+                                childCall.setParentCall(conferenceCall);
                             }
                         } else {
                             //Log.w(this, "setIsConferenced, unknown call id: %s", args.arg1);
@@ -228,12 +226,32 @@
                     break;
                 }
                 case MSG_ADD_CONFERENCE_CALL: {
-                    Call conferenceCall = mCallIdMapper.getCall(msg.obj);
-                    if (mPendingConferenceCalls.remove(conferenceCall)) {
-                        Log.v(this, "confirming conf call %s", conferenceCall);
-                        conferenceCall.confirmConference();
-                    } else {
-                        //Log.w(this, "addConference, unknown call id: %s", callId);
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String id = (String) args.arg1;
+                        if (mCallIdMapper.getCall(id) != null) {
+                            Log.w(this, "Attempting to add a conference call using an existing " +
+                                    "call id %s", id);
+                            break;
+                        }
+                        ParcelableConference parcelableConference =
+                                (ParcelableConference) args.arg2;
+                        // need to create a new Call
+                        Call conferenceCall = mCallsManager.createConferenceCall(
+                                null, parcelableConference);
+                        mCallIdMapper.addCall(conferenceCall, id);
+                        conferenceCall.setConnectionService(ConnectionServiceWrapper.this);
+
+                        Log.d(this, "adding children to conference");
+                        for (String callId : parcelableConference.getConnectionIds()) {
+                            Call childCall = mCallIdMapper.getCall(callId);
+                            Log.d(this, "found child: %s", callId);
+                            if (childCall != null) {
+                                childCall.setParentCall(conferenceCall);
+                            }
+                        }
+                    } finally {
+                        args.recycle();
                     }
                     break;
                 }
@@ -421,7 +439,7 @@
         @Override
         public void setActive(String callId) {
             logIncoming("setActive %s", callId);
-            if (mCallIdMapper.isValidCallId(callId)) {
+            if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper.isValidConferenceId(callId)) {
                 mHandler.obtainMessage(MSG_SET_ACTIVE, callId).sendToTarget();
             }
         }
@@ -457,7 +475,8 @@
         public void setDisconnected(
                 String callId, int disconnectCause, String disconnectMessage) {
             logIncoming("setDisconnected %s %d %s", callId, disconnectCause, disconnectMessage);
-            if (mCallIdMapper.isValidCallId(callId)) {
+            if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper.isValidConferenceId(callId)) {
+                Log.d(this, "disconnect call %s", callId);
                 SomeArgs args = SomeArgs.obtain();
                 args.arg1 = callId;
                 args.arg2 = disconnectMessage;
@@ -469,7 +488,7 @@
         @Override
         public void setOnHold(String callId) {
             logIncoming("setOnHold %s", callId);
-            if (mCallIdMapper.isValidCallId(callId)) {
+            if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper.isValidConferenceId(callId)) {
                 mHandler.obtainMessage(MSG_SET_ON_HOLD, callId).sendToTarget();
             }
         }
@@ -486,8 +505,9 @@
         @Override
         public void removeCall(String callId) {
             logIncoming("removeCall %s", callId);
-            if (mCallIdMapper.isValidCallId(callId)) {
+            if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper.isValidConferenceId(callId)) {
                 mHandler.obtainMessage(MSG_REMOVE_CALL, callId).sendToTarget();
+                mHandler.obtainMessage(MSG_REMOVE_CALL, callId);
             }
         }
 
@@ -504,7 +524,7 @@
         public void setIsConferenced(String callId, String conferenceCallId) {
             logIncoming("setIsConferenced %s %s", callId, conferenceCallId);
             if (mCallIdMapper.isValidCallId(callId) &&
-                    mCallIdMapper.isValidCallId(conferenceCallId)) {
+                    mCallIdMapper.isValidConferenceId(conferenceCallId)) {
                 SomeArgs args = SomeArgs.obtain();
                 args.arg1 = callId;
                 args.arg2 = conferenceCallId;
@@ -513,11 +533,14 @@
         }
 
         @Override
-        public void addConferenceCall(String callId) {
-            logIncoming("addConferenceCall %s", callId);
-            if (mCallIdMapper.isValidCallId(callId)) {
-                mHandler.obtainMessage(MSG_ADD_CONFERENCE_CALL, callId).sendToTarget();
-            }
+        public void addConferenceCall(String callId, ParcelableConference parcelableConference) {
+            logIncoming("addConferenceCall %s %s", callId, parcelableConference);
+            // We do not check call Ids here because we do not yet know the call ID for new
+            // conference calls.
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = parcelableConference;
+            mHandler.obtainMessage(MSG_ADD_CONFERENCE_CALL, args).sendToTarget();
         }
 
         @Override
@@ -874,25 +897,13 @@
         }
     }
 
-    void conference(final Call conferenceCall, Call call) {
-        final String conferenceId = mCallIdMapper.getCallId(call);
+    void conference(final Call call, Call otherCall) {
         final String callId = mCallIdMapper.getCallId(call);
-        if (conferenceId != null && callId != null &&
-                isServiceValid("conference")) {
+        final String otherCallId = mCallIdMapper.getCallId(otherCall);
+        if (callId != null && otherCallId != null && isServiceValid("conference")) {
             try {
-                conferenceCall.setConnectionService(this);
-                mPendingConferenceCalls.add(conferenceCall);
-                mHandler.postDelayed(new Runnable() {
-                    @Override public void run() {
-                        if (mPendingConferenceCalls.remove(conferenceCall)) {
-                            conferenceCall.expireConference();
-                            Log.i(this, "Conference call expired: %s", conferenceCall);
-                        }
-                    }
-                }, Timeouts.getConferenceCallExpireMillis());
-
-                logOutgoing("conference %s %s", conferenceId, callId);
-                mServiceInterface.conference(conferenceId, callId);
+                logOutgoing("conference %s %s", callId, otherCallId);
+                mServiceInterface.conference(callId, otherCallId);
             } catch (RemoteException ignored) {
             }
         }
diff --git a/src/com/android/telecomm/InCallController.java b/src/com/android/telecomm/InCallController.java
index 47f7f2b..00ed147 100644
--- a/src/com/android/telecomm/InCallController.java
+++ b/src/com/android/telecomm/InCallController.java
@@ -195,7 +195,7 @@
 
     @Override
     public void onIsConferencedChanged(Call call) {
-        Log.v(this, "onIsConferencedChanged %s", call);
+        Log.d(this, "onIsConferencedChanged %s", call);
         updateCall(call);
     }
 
@@ -292,7 +292,7 @@
         if (mInCallService != null) {
             try {
                 ParcelableCall parcelableCall = toParcelableCall(call);
-                Log.v(this, "updateCall %s ==> %s", call, parcelableCall);
+                Log.d(this, "updateCall %s ==> %s", call, parcelableCall);
                 mInCallService.updateCall(parcelableCall);
             } catch (RemoteException ignored) {
             }
diff --git a/src/com/android/telecomm/Timeouts.java b/src/com/android/telecomm/Timeouts.java
index 3ae3f1d..3ff0575 100644
--- a/src/com/android/telecomm/Timeouts.java
+++ b/src/com/android/telecomm/Timeouts.java
@@ -51,11 +51,4 @@
     public static long getDirectToVoicemailMillis() {
         return get("direct_to_voicemail_ms", 500L);
     }
-
-    /**
-     * Returns the amount of time that a connection service has to respond to a "conference" action.
-     */
-    public static long getConferenceCallExpireMillis() {
-        return get("conference_call_expire_ms", 15 * 1000L);
-    }
 }