Merge "Delete unused methods."
diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java
index 6a36657..bb079b5 100644
--- a/InCallUI/src/com/android/incallui/Call.java
+++ b/InCallUI/src/com/android/incallui/Call.java
@@ -26,6 +26,7 @@
 import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.primitives.Ints;
 
+import java.util.List;
 import java.util.Locale;
 
 /**
@@ -105,6 +106,8 @@
     private GatewayInfo mGatewayInfo;
     private CallServiceDescriptor mCurrentCallServiceDescriptor;
     private CallServiceDescriptor mHandoffCallServiceDescriptor;
+    private String mParentCallId;
+    private List<String> mChildCallIds;
 
     public Call(String callId) {
         mCallId = callId;
@@ -118,7 +121,7 @@
         if (mGatewayInfo != null) {
             return mGatewayInfo.getOriginalHandle().getSchemeSpecificPart();
         }
-        return getHandle().getSchemeSpecificPart();
+        return mHandle == null ? null : mHandle.getSchemeSpecificPart();
     }
 
     public Uri getHandle() {
@@ -130,7 +133,11 @@
     }
 
     public int getState() {
-        return mState;
+        if (mParentCallId != null) {
+            return State.CONFERENCED;
+        } else {
+            return mState;
+        }
     }
 
     public void setState(int state) {
@@ -183,12 +190,8 @@
         return mConnectTimeMillis;
     }
 
-    public ImmutableSortedSet<Integer> getChildCallIds() {
-        return ImmutableSortedSet.of();
-    }
-
     public boolean isConferenceCall() {
-        return false;
+        return mChildCallIds != null && !mChildCallIds.isEmpty();
     }
 
     public GatewayInfo getGatewayInfo() {
@@ -220,8 +223,29 @@
         mHandoffCallServiceDescriptor = descriptor;
     }
 
+    public void setChildCallIds(List<String> callIds) {
+        mChildCallIds = callIds;
+    }
+
+    public List<String> getChildCallIds() {
+        return mChildCallIds;
+    }
+
+    public void setParentId(String callId) {
+        mParentCallId = callId;
+    }
+
+    public String getParentId() {
+        return mParentCallId;
+    }
+
     @Override
     public String toString() {
-        return String.format(Locale.US, "[%s, %s]", mCallId, State.toString(mState));
+        return String.format(Locale.US, "[%s, %s, %s, children:%s, parent:%s]",
+                mCallId,
+                State.toString(mState),
+                CallCapabilities.toString(mCapabilities),
+                mChildCallIds,
+                mParentCallId);
     }
 }
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index e899bf6..bcb4a55 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -211,7 +211,7 @@
     }
 
     public void mergeClicked() {
-        TelecommAdapter.getInstance().merge();
+        TelecommAdapter.getInstance().merge(mCall.getCallId());
     }
 
     public void addCallClicked() {
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 335fcfd..29d0b19 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -493,7 +493,7 @@
             // (2) Attempt actions on Generic conference calls
             if (activeCall.isConferenceCall() && isGeneric) {
                 if (canMerge) {
-                    TelecommAdapter.getInstance().merge();
+                    TelecommAdapter.getInstance().merge(activeCall.getCallId());
                     return true;
                 } else if (canSwap) {
                     TelecommAdapter.getInstance().swap();
diff --git a/InCallUI/src/com/android/incallui/InCallServiceImpl.java b/InCallUI/src/com/android/incallui/InCallServiceImpl.java
index e608570..f98d7f1 100644
--- a/InCallUI/src/com/android/incallui/InCallServiceImpl.java
+++ b/InCallUI/src/com/android/incallui/InCallServiceImpl.java
@@ -17,11 +17,13 @@
 package com.android.incallui;
 
 import android.telecomm.CallAudioState;
+import android.telecomm.CallCapabilities;
 import android.telecomm.CallState;
-import android.telecomm.ConnectionRequest;
+import android.telecomm.GatewayInfo;
 import android.telecomm.InCallAdapter;
 import android.telecomm.InCallCall;
 import android.telecomm.InCallService;
+import android.telephony.DisconnectCause;
 
 import com.google.common.collect.ImmutableList;
 
@@ -40,6 +42,7 @@
         InCallPresenter inCallPresenter = InCallPresenter.getInstance();
         inCallPresenter.setUp(
                 getApplicationContext(), CallList.getInstance(), AudioModeProvider.getInstance());
+        TelecommAdapter.getInstance().setContext(this);
     }
 
     /** {@inheritDoc} */
@@ -47,6 +50,7 @@
         Log.v(this, "onDestroy");
         // Tear down the InCall system
         TelecommAdapter.getInstance().setAdapter(null);
+        TelecommAdapter.getInstance().setContext(null);
         CallList.getInstance().clearOnDisconnect();
         InCallPresenter.getInstance().tearDown();
     }
@@ -59,9 +63,10 @@
 
     /** {@inheritDoc} */
     @Override protected void addCall(InCallCall telecommCall) {
-        Log.v(this, "addCall, state: " + telecommCall.getState());
         Call call = new Call(telecommCall.getId());
         updateCall(call, telecommCall);
+        Log.i(this, "addCall: " + call);
+
         if (call.getState() == Call.State.INCOMING) {
             CallList.getInstance().onIncoming(call, EMPTY_RESPONSE_TEXTS);
         } else {
@@ -77,9 +82,9 @@
             return;
         }
 
-        Log.v(this, "updateCall: " + call);
         int oldState = call.getState();
         updateCall(call, telecommCall);
+        Log.i(this, "updateCall: " + telecommCall + " => " + call);
 
         if (oldState != call.getState() && call.getState() == Call.State.DISCONNECTED) {
             CallList.getInstance().onDisconnect(call);
@@ -123,6 +128,8 @@
         call.setCurrentCallServiceDescriptor(telecommCall.getCurrentCallServiceDescriptor());
         call.setHandoffCallServiceDescriptor(telecommCall.getHandoffCallServiceDescriptor());
         call.setState(translateState(telecommCall.getState()));
+        call.setParentId(telecommCall.getParentCallId());
+        call.setChildCallIds(telecommCall.getChildCallIds());
     }
 
     private static int translateState(CallState state) {
diff --git a/InCallUI/src/com/android/incallui/TelecommAdapter.java b/InCallUI/src/com/android/incallui/TelecommAdapter.java
index 1828678..4b0aff3 100644
--- a/InCallUI/src/com/android/incallui/TelecommAdapter.java
+++ b/InCallUI/src/com/android/incallui/TelecommAdapter.java
@@ -16,6 +16,9 @@
 
 package com.android.incallui;
 
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
 import android.os.Looper;
 import android.telecomm.InCallAdapter;
 
@@ -23,7 +26,10 @@
 
 /** Wrapper around {@link InCallAdapter} that only forwards calls to the adapter when it's valid. */
 final class TelecommAdapter {
+    private static final String ADD_CALL_MODE_KEY = "add_call_mode";
+
     private static TelecommAdapter sInstance;
+    private Context mContext;
     private InCallAdapter mAdapter;
 
     static TelecommAdapter getInstance() {
@@ -37,6 +43,10 @@
     private TelecommAdapter() {
     }
 
+    void setContext(Context context) {
+        mContext = context;
+    }
+
     void setAdapter(InCallAdapter adapter) {
         mAdapter = adapter;
     }
@@ -99,11 +109,19 @@
     }
 
     void separateCall(String callId) {
-        Log.wtf(this, "separateCall not implemented");
+        if (mAdapter != null) {
+            mAdapter.splitFromConference(callId);
+        } else {
+            Log.e(this, "error separateCall, mAdapter is null.");
+        }
     }
 
-    void merge() {
-        Log.wtf(this, "merge not implemented");
+    void merge(String callId) {
+        if (mAdapter != null) {
+            mAdapter.conference(callId);
+        } else {
+            Log.e(this, "error merge, mAdapter is null.");
+        }
     }
 
     void swap() {
@@ -111,7 +129,24 @@
     }
 
     void addCall() {
-        Log.wtf(this, "addCall not implemented");
+        if (mContext != null) {
+            Intent intent = new Intent(Intent.ACTION_DIAL);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            // when we request the dialer come up, we also want to inform
+            // it that we're going through the "add call" option from the
+            // InCallScreen / PhoneUtils.
+            intent.putExtra(ADD_CALL_MODE_KEY, true);
+            try {
+                Log.d(this, "Sending the add Call intent");
+                mContext.startActivity(intent);
+            } catch (ActivityNotFoundException e) {
+                // This is rather rare but possible.
+                // Note: this method is used even when the phone is encrypted. At that moment
+                // the system may not find any Activity which can accept this Intent.
+                Log.e(this, "Activity for adding calls isn't found.", e);
+            }
+        }
     }
 
     void playDtmfTone(String callId, char digit) {