diff --git a/src/com/android/telecomm/ConnectionServiceWrapper.java b/src/com/android/telecomm/ConnectionServiceWrapper.java
new file mode 100644
index 0000000..0ae8d20
--- /dev/null
+++ b/src/com/android/telecomm/ConnectionServiceWrapper.java
@@ -0,0 +1,886 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.telecomm;
+
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telecomm.CallAudioState;
+import android.telecomm.ConnectionService;
+import android.telecomm.CallServiceDescriptor;
+import android.telecomm.ConnectionRequest;
+import android.telecomm.GatewayInfo;
+import android.telecomm.TelecommConstants;
+import android.telephony.DisconnectCause;
+
+import com.android.internal.os.SomeArgs;
+
+import com.android.internal.telecomm.IConnectionService;
+import com.android.internal.telecomm.IConnectionServiceAdapter;
+import com.android.internal.telecomm.ICallServiceProvider;
+import com.android.internal.telecomm.ICallVideoProvider;
+import com.android.internal.telecomm.RemoteServiceCallback;
+import com.android.telecomm.BaseRepository.LookupCallback;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import org.apache.http.conn.ClientConnectionRequest;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Wrapper for {@link IConnectionService}s, handles binding to {@link IConnectionService} and keeps
+ * track of when the object can safely be unbound. Other classes should not use
+ * {@link IConnectionService} directly and instead should use this class to invoke methods of
+ * {@link IConnectionService}.
+ */
+final class ConnectionServiceWrapper extends ServiceBinder<IConnectionService> {
+    private static final int MSG_NOTIFY_INCOMING_CALL = 1;
+    private static final int MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL = 2;
+    private static final int MSG_HANDLE_FAILED_OUTGOING_CALL = 3;
+    private static final int MSG_CANCEL_OUTGOING_CALL = 4;
+    private static final int MSG_SET_ACTIVE = 5;
+    private static final int MSG_SET_RINGING = 6;
+    private static final int MSG_SET_DIALING = 7;
+    private static final int MSG_SET_DISCONNECTED = 8;
+    private static final int MSG_SET_ON_HOLD = 9;
+    private static final int MSG_SET_REQUESTING_RINGBACK = 10;
+    private static final int MSG_CAN_CONFERENCE = 11;
+    private static final int MSG_SET_IS_CONFERENCED = 12;
+    private static final int MSG_ADD_CONFERENCE_CALL = 13;
+    private static final int MSG_REMOVE_CALL = 14;
+    private static final int MSG_ON_POST_DIAL_WAIT = 15;
+    private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 16;
+    private static final int MSG_SET_CALL_VIDEO_PROVIDER = 17;
+    private static final int MSG_SET_FEATURES = 18;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            Call call;
+            switch (msg.what) {
+                case MSG_NOTIFY_INCOMING_CALL: {
+                    ConnectionRequest request = (ConnectionRequest) msg.obj;
+                    call = mCallIdMapper.getCall(request.getCallId());
+                    if (call != null && mPendingIncomingCalls.remove(call) &&
+                            call.isIncoming()) {
+                        mIncomingCallsManager.handleSuccessfulIncomingCall(call, request);
+                    } else {
+                        // TODO(santoscordon): For this an the other commented logging, we need
+                        // to reenable it.  At the moment all ConnectionServiceAdapters receive
+                        // notification of changes to all calls, even calls which it may not own
+                        // (ala remote connections). We need to fix that and then uncomment the
+                        // logging calls here.
+                        //Log.w(this, "notifyIncomingCall, unknown incoming call: %s, id: %s",
+                        //        call, request.getId());
+                    }
+                    break;
+                }
+                case MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL: {
+                    ConnectionRequest request = (ConnectionRequest) msg.obj;
+                    if (mPendingOutgoingCalls.containsKey(request.getCallId())) {
+                        mPendingOutgoingCalls.remove(
+                                request.getCallId()).onOutgoingCallSuccess();
+                    } else {
+                        //Log.w(this, "handleSuccessfulOutgoingCall, unknown call: %s", callId);
+                    }
+                    break;
+                }
+                case MSG_HANDLE_FAILED_OUTGOING_CALL: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        ConnectionRequest request = (ConnectionRequest) msg.obj;
+                        int statusCode = args.argi1;
+                        String statusMsg = (String) args.arg2;
+                        // TODO(santoscordon): Do something with 'reason' or get rid of it.
+
+                        if (mPendingOutgoingCalls.containsKey(request.getCallId())) {
+                            mPendingOutgoingCalls.remove(request.getCallId())
+                                    .onOutgoingCallFailure(statusCode, statusMsg);
+                            mCallIdMapper.removeCall(request.getCallId());
+                        } else {
+                            //Log.w(this, "handleFailedOutgoingCall, unknown call: %s", callId);
+                        }
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+                case MSG_CANCEL_OUTGOING_CALL: {
+                    ConnectionRequest request = (ConnectionRequest) msg.obj;
+                    if (mPendingOutgoingCalls.containsKey(request.getCallId())) {
+                        mPendingOutgoingCalls.remove(
+                                request.getCallId()).onOutgoingCallCancel();
+                    } else {
+                        //Log.w(this, "cancelOutgoingCall, unknown call: %s", callId);
+                    }
+                    break;
+                }
+                case MSG_SET_ACTIVE:
+                    call = mCallIdMapper.getCall(msg.obj);
+                    if (call != null) {
+                        mCallsManager.markCallAsActive(call);
+                    } else {
+                        //Log.w(this, "setActive, unknown call id: %s", msg.obj);
+                    }
+                    break;
+                case MSG_SET_RINGING:
+                    call = mCallIdMapper.getCall(msg.obj);
+                    if (call != null) {
+                        mCallsManager.markCallAsRinging(call);
+                    } else {
+                        //Log.w(this, "setRinging, unknown call id: %s", msg.obj);
+                    }
+                    break;
+                case MSG_SET_DIALING:
+                    call = mCallIdMapper.getCall(msg.obj);
+                    if (call != null) {
+                        mCallsManager.markCallAsDialing(call);
+                    } else {
+                        //Log.w(this, "setDialing, unknown call id: %s", msg.obj);
+                    }
+                    break;
+                case MSG_SET_DISCONNECTED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        call = mCallIdMapper.getCall(args.arg1);
+                        String disconnectMessage = (String) args.arg2;
+                        int disconnectCause = args.argi1;
+                        if (call != null) {
+                            mCallsManager.markCallAsDisconnected(call, disconnectCause,
+                                    disconnectMessage);
+                        } else {
+                            //Log.w(this, "setDisconnected, unknown call id: %s", args.arg1);
+                        }
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+                case MSG_SET_ON_HOLD:
+                    call = mCallIdMapper.getCall(msg.obj);
+                    if (call != null) {
+                        mCallsManager.markCallAsOnHold(call);
+                    } else {
+                        //Log.w(this, "setOnHold, unknown call id: %s", msg.obj);
+                    }
+                    break;
+                case MSG_SET_REQUESTING_RINGBACK: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        call = mCallIdMapper.getCall(args.arg1);
+                        boolean ringback = (boolean) args.arg2;
+                        if (call != null) {
+                            call.setRequestingRingback(ringback);
+                        } else {
+                            //Log.w(this, "setRingback, unknown call id: %s", args.arg1);
+                        }
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+                case MSG_CAN_CONFERENCE: {
+                    call = mCallIdMapper.getCall(msg.obj);
+                    if (call != null) {
+                        call.setIsConferenceCapable(msg.arg1 == 1);
+                    } else {
+                        //Log.w(ConnectionServiceWrapper.this,
+                        //      "canConference, unknown call id: %s", msg.obj);
+                    }
+                    break;
+                }
+                case MSG_SET_IS_CONFERENCED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        Call childCall = mCallIdMapper.getCall(args.arg1);
+                        if (childCall != null) {
+                            String conferenceCallId = (String) args.arg2;
+                            if (conferenceCallId == null) {
+                                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);
+                                }
+                            }
+                        } else {
+                            //Log.w(this, "setIsConferenced, unknown call id: %s", args.arg1);
+                        }
+                    } finally {
+                        args.recycle();
+                    }
+                    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);
+                    }
+                    break;
+                }
+                case MSG_REMOVE_CALL:
+                    break;
+                case MSG_ON_POST_DIAL_WAIT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        call = mCallIdMapper.getCall(args.arg1);
+                        if (call != null) {
+                            String remaining = (String) args.arg2;
+                            call.onPostDialWait(remaining);
+                        } else {
+                            //Log.w(this, "onPostDialWait, unknown call id: %s", args.arg1);
+                        }
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+                case MSG_QUERY_REMOTE_CALL_SERVICES: {
+                    ConnectionServiceWrapper.this.queryRemoteConnectionServices(
+                            (RemoteServiceCallback) msg.obj);
+                    break;
+                }
+                case MSG_SET_CALL_VIDEO_PROVIDER: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        call = mCallIdMapper.getCall(args.arg1);
+                        ICallVideoProvider callVideoProvider = (ICallVideoProvider) args.arg2;
+                        if (call != null) {
+                            call.setCallVideoProvider(callVideoProvider);
+                        }
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+                case MSG_SET_FEATURES: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        call = mCallIdMapper.getCall(args.arg1);
+                        int features = (int) args.arg2;
+                        if (call != null) {
+                            call.setFeatures(features);
+                        }
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+            }
+        }
+    };
+
+    private final class Adapter extends IConnectionServiceAdapter.Stub {
+        /** {@inheritDoc} */
+        @Override
+        public void notifyIncomingCall(ConnectionRequest request) {
+            logIncoming("notifyIncomingCall %s", request);
+            mCallIdMapper.checkValidCallId(request.getCallId());
+            mHandler.obtainMessage(MSG_NOTIFY_INCOMING_CALL, request).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void handleSuccessfulOutgoingCall(ConnectionRequest request) {
+            logIncoming("handleSuccessfulOutgoingCall %s", request);
+            mCallIdMapper.checkValidCallId(request.getCallId());
+            mHandler.obtainMessage(MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL, request).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void handleFailedOutgoingCall(
+                ConnectionRequest request,
+                int errorCode,
+                String errorMsg) {
+            logIncoming("handleFailedOutgoingCall %s %d %s", request, errorCode, errorMsg);
+            mCallIdMapper.checkValidCallId(request.getCallId());
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = request;
+            args.argi1 = errorCode;
+            args.arg2 = errorMsg;
+            mHandler.obtainMessage(MSG_HANDLE_FAILED_OUTGOING_CALL, args).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void cancelOutgoingCall(ConnectionRequest request) {
+            logIncoming("cancelOutgoingCall %s", request);
+            mCallIdMapper.checkValidCallId(request.getCallId());
+            mHandler.obtainMessage(MSG_CANCEL_OUTGOING_CALL, request).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void setActive(String callId) {
+            logIncoming("setActive %s", callId);
+            mCallIdMapper.checkValidCallId(callId);
+            mHandler.obtainMessage(MSG_SET_ACTIVE, callId).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void setRinging(String callId) {
+            logIncoming("setRinging %s", callId);
+            mCallIdMapper.checkValidCallId(callId);
+            mHandler.obtainMessage(MSG_SET_RINGING, callId).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void setCallVideoProvider(String callId, ICallVideoProvider callVideoProvider) {
+            logIncoming("setCallVideoProvider %s", callId);
+            mCallIdMapper.checkValidCallId(callId);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = callVideoProvider;
+            mHandler.obtainMessage(MSG_SET_CALL_VIDEO_PROVIDER, args).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void setDialing(String callId) {
+            logIncoming("setDialing %s", callId);
+            mCallIdMapper.checkValidCallId(callId);
+            mHandler.obtainMessage(MSG_SET_DIALING, callId).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void setDisconnected(
+                String callId, int disconnectCause, String disconnectMessage) {
+            logIncoming("setDisconnected %s %d %s", callId, disconnectCause, disconnectMessage);
+            mCallIdMapper.checkValidCallId(callId);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = disconnectMessage;
+            args.argi1 = disconnectCause;
+            mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void setOnHold(String callId) {
+            logIncoming("setOnHold %s", callId);
+            mCallIdMapper.checkValidCallId(callId);
+            mHandler.obtainMessage(MSG_SET_ON_HOLD, callId).sendToTarget();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void setRequestingRingback(String callId, boolean ringback) {
+            logIncoming("setRequestingRingback %s %b", callId, ringback);
+            mCallIdMapper.checkValidCallId(callId);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = ringback;
+            mHandler.obtainMessage(MSG_SET_REQUESTING_RINGBACK, args).sendToTarget();
+        }
+
+        /** ${inheritDoc} */
+        @Override
+        public void removeCall(String callId) {
+            logIncoming("removeCall %s", callId);
+        }
+
+        /** ${inheritDoc} */
+        @Override
+        public void setCanConference(String callId, boolean canConference) {
+            logIncoming("setCanConference %s %b", callId, canConference);
+            mHandler.obtainMessage(MSG_CAN_CONFERENCE, canConference ? 1 : 0, 0, callId)
+                    .sendToTarget();
+        }
+
+        /** ${inheritDoc} */
+        @Override
+        public void setIsConferenced(String callId, String conferenceCallId) {
+            logIncoming("setIsConferenced %s %s", callId, conferenceCallId);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = conferenceCallId;
+            mHandler.obtainMessage(MSG_SET_IS_CONFERENCED, args).sendToTarget();
+        }
+
+        /** ${InheritDoc} */
+        @Override
+        public void addConferenceCall(String callId) {
+            logIncoming("addConferenceCall %s", callId);
+            mCallIdMapper.checkValidCallId(callId);
+            mHandler.obtainMessage(MSG_ADD_CONFERENCE_CALL, callId).sendToTarget();
+        }
+
+        @Override
+        public void onPostDialWait(String callId, String remaining) throws RemoteException {
+            logIncoming("onPostDialWait %s %s", callId, remaining);
+            mCallIdMapper.checkValidCallId(callId);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = remaining;
+            mHandler.obtainMessage(MSG_ON_POST_DIAL_WAIT, args).sendToTarget();
+        }
+
+        /** ${inheritDoc} */
+        @Override
+        public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
+            logIncoming("queryRemoteCSs");
+            mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
+        }
+
+        @Override
+        public void setFeatures(String callId, int features) {
+            logIncoming("setFeatures %s %d", callId, features);
+            mCallIdMapper.checkValidCallId(callId);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = features;
+            mHandler.obtainMessage(MSG_SET_FEATURES, args).sendToTarget();
+        }
+    }
+
+    private final Adapter mAdapter = new Adapter();
+    private final CallsManager mCallsManager = CallsManager.getInstance();
+    private final Set<Call> mPendingIncomingCalls = new HashSet<>();
+    private final Set<Call> mPendingConferenceCalls = new HashSet<>();
+    private final CallServiceDescriptor mDescriptor;
+    private final CallIdMapper mCallIdMapper = new CallIdMapper("ConnectionService");
+    private final IncomingCallsManager mIncomingCallsManager;
+    private final Map<String, OutgoingCallResponse> mPendingOutgoingCalls = new HashMap<>();
+
+    private Binder mBinder = new Binder();
+    private IConnectionService mServiceInterface;
+    private final CallServiceRepository mCallServiceRepository;
+
+    /**
+     * Creates a call-service for the specified descriptor.
+     *
+     * @param descriptor The call-service descriptor from
+     *            {@link ICallServiceProvider#lookupCallServices}.
+     * @param incomingCallsManager Manages the incoming call initialization flow.
+     * @param callServiceRepository Connection service repository.
+     */
+    ConnectionServiceWrapper(
+            CallServiceDescriptor descriptor,
+            IncomingCallsManager incomingCallsManager,
+            CallServiceRepository callServiceRepository) {
+        super(TelecommConstants.ACTION_CONNECTION_SERVICE, descriptor.getServiceComponent());
+        mDescriptor = descriptor;
+        mIncomingCallsManager = incomingCallsManager;
+        mCallServiceRepository = callServiceRepository;
+    }
+
+    CallServiceDescriptor getDescriptor() {
+        return mDescriptor;
+    }
+
+    /** See {@link IConnectionService#addConnectionServiceAdapter}. */
+    private void addConnectionServiceAdapter(IConnectionServiceAdapter adapter) {
+        if (isServiceValid("addConnectionServiceAdapter")) {
+            try {
+                logOutgoing("addConnectionServiceAdapter%s", adapter);
+                mServiceInterface.addConnectionServiceAdapter(adapter);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /**
+     * Attempts to place the specified call, see {@link IConnectionService#call}. Returns the result
+     * asynchronously through the specified callback.
+     */
+    void call(final Call call, final OutgoingCallResponse callResponse) {
+        Log.d(this, "call(%s) via %s.", call, getComponentName());
+        BindCallback callback = new BindCallback() {
+            @Override
+            public void onSuccess() {
+                String callId = mCallIdMapper.getCallId(call);
+                mPendingOutgoingCalls.put(callId, callResponse);
+
+                GatewayInfo gatewayInfo = call.getGatewayInfo();
+                Bundle extras = call.getExtras();
+                if (gatewayInfo != null && gatewayInfo.getGatewayProviderPackageName() != null &&
+                        gatewayInfo.getOriginalHandle() != null) {
+                    extras = (Bundle) extras.clone();
+                    extras.putString(
+                            NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_PROVIDER_PACKAGE,
+                            gatewayInfo.getGatewayProviderPackageName());
+                    extras.putParcelable(
+                            NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_ORIGINAL_URI,
+                            gatewayInfo.getOriginalHandle());
+                }
+                ConnectionRequest request = new ConnectionRequest(callId, call.getHandle(), extras);
+
+                try {
+                    mServiceInterface.call(request);
+                } catch (RemoteException e) {
+                    Log.e(this, e, "Failure to call -- %s", getDescriptor());
+                    mPendingOutgoingCalls.remove(callId).onOutgoingCallFailure(
+                            DisconnectCause.ERROR_UNSPECIFIED, e.toString());
+                }
+            }
+
+            @Override
+            public void onFailure() {
+                Log.e(this, new Exception(), "Failure to call %s", getDescriptor());
+                callResponse.onOutgoingCallFailure(DisconnectCause.ERROR_UNSPECIFIED, null);
+            }
+        };
+
+        mBinder.bind(callback);
+    }
+
+    /** @see ConnectionService#abort(String) */
+    void abort(Call call) {
+        // Clear out any pending outgoing call data
+        String callId = mCallIdMapper.getCallId(call);
+
+        // If still bound, tell the connection service to abort.
+        if (isServiceValid("abort")) {
+            try {
+                logOutgoing("abort %s", callId);
+                mServiceInterface.abort(callId);
+            } catch (RemoteException e) {
+            }
+        }
+
+        removeCall(call);
+    }
+
+    /** @see ConnectionService#hold(String) */
+    void hold(Call call) {
+        if (isServiceValid("hold")) {
+            try {
+                logOutgoing("hold %s", mCallIdMapper.getCallId(call));
+                mServiceInterface.hold(mCallIdMapper.getCallId(call));
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /** @see ConnectionService#unhold(String) */
+    void unhold(Call call) {
+        if (isServiceValid("unhold")) {
+            try {
+                logOutgoing("unhold %s", mCallIdMapper.getCallId(call));
+                mServiceInterface.unhold(mCallIdMapper.getCallId(call));
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /** @see ConnectionService#onAudioStateChanged(String,CallAudioState) */
+    void onAudioStateChanged(Call activeCall, CallAudioState audioState) {
+        if (isServiceValid("onAudioStateChanged")) {
+            try {
+                logOutgoing("onAudioStateChanged %s %s",
+                        mCallIdMapper.getCallId(activeCall), audioState);
+                mServiceInterface.onAudioStateChanged(mCallIdMapper.getCallId(activeCall),
+                        audioState);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /**
+     * Starts retrieval of details for an incoming call. Details are returned through the
+     * call-service adapter using the specified call ID. Upon failure, the specified error callback
+     * is invoked. Can be invoked even when the connection service is unbound. See
+     * {@link IConnectionService#createIncomingCall}.
+     *
+     * @param call The call used for the incoming call.
+     * @param extras The {@link ConnectionService}-provided extras which need to be sent back.
+     * @param errorCallback The callback to invoke upon failure.
+     */
+    void createIncomingCall(final Call call, final Bundle extras, final Runnable errorCallback) {
+        Log.d(this, "createIncomingCall(%s) via %s.", call, getComponentName());
+        BindCallback callback = new BindCallback() {
+            @Override
+            public void onSuccess() {
+                if (isServiceValid("createIncomingCall")) {
+                    mPendingIncomingCalls.add(call);
+                    String callId = mCallIdMapper.getCallId(call);
+                    logOutgoing("createIncomingCall %s %s", callId, extras);
+                    ConnectionRequest request = new ConnectionRequest(
+                            callId, call.getHandle(), extras);
+                    try {
+                        mServiceInterface.createIncomingCall(request);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+
+            @Override
+            public void onFailure() {
+                errorCallback.run();
+            }
+        };
+
+        mBinder.bind(callback);
+    }
+
+    /** @see ConnectionService#disconnect(String) */
+    void disconnect(Call call) {
+        if (isServiceValid("disconnect")) {
+            try {
+                logOutgoing("disconnect %s", mCallIdMapper.getCallId(call));
+                mServiceInterface.disconnect(mCallIdMapper.getCallId(call));
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /** @see ConnectionService#answer(String) */
+    void answer(Call call) {
+        if (isServiceValid("answer")) {
+            try {
+                logOutgoing("answer %s", mCallIdMapper.getCallId(call));
+                mServiceInterface.answer(mCallIdMapper.getCallId(call));
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /** @see ConnectionService#reject(String) */
+    void reject(Call call) {
+        if (isServiceValid("reject")) {
+            try {
+                logOutgoing("reject %s", mCallIdMapper.getCallId(call));
+                mServiceInterface.reject(mCallIdMapper.getCallId(call));
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /** @see ConnectionService#playDtmfTone(String,char) */
+    void playDtmfTone(Call call, char digit) {
+        if (isServiceValid("playDtmfTone")) {
+            try {
+                logOutgoing("playDtmfTone %s %c", mCallIdMapper.getCallId(call), digit);
+                mServiceInterface.playDtmfTone(mCallIdMapper.getCallId(call), digit);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /** @see ConnectionService#stopDtmfTone(String) */
+    void stopDtmfTone(Call call) {
+        if (isServiceValid("stopDtmfTone")) {
+            try {
+                logOutgoing("stopDtmfTone %s", mCallIdMapper.getCallId(call));
+                mServiceInterface.stopDtmfTone(mCallIdMapper.getCallId(call));
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    void addCall(Call call) {
+        if (mCallIdMapper.getCallId(call) == null) {
+            mCallIdMapper.addCall(call);
+        }
+    }
+
+    /**
+     * Associates newCall with this connection service by replacing callToReplace.
+     */
+    void replaceCall(Call newCall, Call callToReplace) {
+        Preconditions.checkState(callToReplace.getConnectionService() == this);
+        mCallIdMapper.replaceCall(newCall, callToReplace);
+    }
+
+    void removeCall(Call call) {
+        mPendingIncomingCalls.remove(call);
+
+        OutgoingCallResponse outgoingResultCallback =
+                mPendingOutgoingCalls.remove(mCallIdMapper.getCallId(call));
+        if (outgoingResultCallback != null) {
+            outgoingResultCallback.onOutgoingCallFailure(DisconnectCause.ERROR_UNSPECIFIED, null);
+        }
+
+        mCallIdMapper.removeCall(call);
+    }
+
+    void onPostDialContinue(Call call, boolean proceed) {
+        if (isServiceValid("onPostDialContinue")) {
+            try {
+                logOutgoing("onPostDialContinue %s %b", mCallIdMapper.getCallId(call), proceed);
+                mServiceInterface.onPostDialContinue(mCallIdMapper.getCallId(call), proceed);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    void onPhoneAccountClicked(Call call) {
+        if (isServiceValid("onPhoneAccountClicked")) {
+            try {
+                logOutgoing("onPhoneAccountClicked %s", mCallIdMapper.getCallId(call));
+                mServiceInterface.onPhoneAccountClicked(mCallIdMapper.getCallId(call));
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    void conference(final Call conferenceCall, Call call) {
+        if (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",
+                        mCallIdMapper.getCallId(conferenceCall),
+                        mCallIdMapper.getCallId(call));
+                mServiceInterface.conference(
+                        mCallIdMapper.getCallId(conferenceCall),
+                        mCallIdMapper.getCallId(call));
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    void splitFromConference(Call call) {
+        if (isServiceValid("splitFromConference")) {
+            try {
+                logOutgoing("splitFromConference %s", mCallIdMapper.getCallId(call));
+                mServiceInterface.splitFromConference(mCallIdMapper.getCallId(call));
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void setServiceInterface(IBinder binder) {
+        if (binder == null) {
+            // We have lost our service connection. Notify the world that this service is done.
+            // We must notify the adapter before CallsManager. The adapter will force any pending
+            // outgoing calls to try the next service. This needs to happen before CallsManager
+            // tries to clean up any calls still associated with this service.
+            handleConnectionServiceDeath();
+            CallsManager.getInstance().handleConnectionServiceDeath(this);
+            mServiceInterface = null;
+        } else {
+            mServiceInterface = IConnectionService.Stub.asInterface(binder);
+            addConnectionServiceAdapter(mAdapter);
+        }
+    }
+
+    /**
+     * Called when the associated connection service dies.
+     */
+    private void handleConnectionServiceDeath() {
+        if (!mPendingOutgoingCalls.isEmpty()) {
+            for (OutgoingCallResponse callback : mPendingOutgoingCalls.values()) {
+                callback.onOutgoingCallFailure(DisconnectCause.ERROR_UNSPECIFIED, null);
+            }
+            mPendingOutgoingCalls.clear();
+        }
+
+        if (!mPendingIncomingCalls.isEmpty()) {
+            // Iterate through a copy because the code inside the loop will modify the original
+            // list.
+            for (Call call : ImmutableList.copyOf(mPendingIncomingCalls)) {
+                Preconditions.checkState(call.isIncoming());
+                mIncomingCallsManager.handleFailedIncomingCall(call);
+            }
+
+            if (!mPendingIncomingCalls.isEmpty()) {
+                Log.wtf(this, "Pending calls did not get cleared.");
+                mPendingIncomingCalls.clear();
+            }
+        }
+
+        mCallIdMapper.clear();
+    }
+
+    private void logIncoming(String msg, Object... params) {
+        Log.d(this, "ConnectionService -> Telecomm: " + msg, params);
+    }
+
+    private void logOutgoing(String msg, Object... params) {
+        Log.d(this, "Telecomm -> ConnectionService: " + msg, params);
+    }
+
+    private void queryRemoteConnectionServices(final RemoteServiceCallback callback) {
+        final List<IBinder> connectionServices = new ArrayList<>();
+        final List<ComponentName> components = new ArrayList<>();
+
+        mCallServiceRepository.lookupServices(new LookupCallback<ConnectionServiceWrapper>() {
+            private int mRemainingResponses;
+
+            /** ${inheritDoc} */
+            @Override
+            public void onComplete(Collection<ConnectionServiceWrapper> services) {
+                mRemainingResponses = services.size() - 1;
+                for (ConnectionServiceWrapper cs : services) {
+                    if (cs != ConnectionServiceWrapper.this) {
+                        final ConnectionServiceWrapper currentConnectionService = cs;
+                        cs.mBinder.bind(new BindCallback() {
+                            @Override
+                            public void onSuccess() {
+                                Log.d(this, "Adding ***** %s",
+                                        currentConnectionService.getDescriptor());
+                                connectionServices.add(
+                                        currentConnectionService.mServiceInterface.asBinder());
+                                components.add(currentConnectionService.getComponentName());
+                                maybeComplete();
+                            }
+
+                            @Override
+                            public void onFailure() {
+                                // add null so that we always add up to totalExpected even if
+                                // some of the connection services fail to bind.
+                                maybeComplete();
+                            }
+
+                            private void maybeComplete() {
+                                if (--mRemainingResponses == 0) {
+                                    try {
+                                        callback.onResult(components, connectionServices);
+                                    } catch (RemoteException ignored) {
+                                    }
+                                }
+                            }
+                        });
+                    }
+                }
+            }
+        });
+    }
+}
