diff --git a/src/com/android/server/telecom/BluetoothHeadsetProxy.java b/src/com/android/server/telecom/BluetoothHeadsetProxy.java
index a43b3cd..e4eed87 100644
--- a/src/com/android/server/telecom/BluetoothHeadsetProxy.java
+++ b/src/com/android/server/telecom/BluetoothHeadsetProxy.java
@@ -36,19 +36,6 @@
         mBluetoothHeadset = headset;
     }
 
-    public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
-            String number, int type) {
-
-        mBluetoothHeadset.clccResponse(index, direction, status, mode, mpty, number, type);
-    }
-
-    public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
-            int type, String name) {
-
-        mBluetoothHeadset.phoneStateChanged(numActive, numHeld, callState, number, type,
-            name);
-    }
-
     public List<BluetoothDevice> getConnectedDevices() {
         return mBluetoothHeadset.getConnectedDevices();
     }
diff --git a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
deleted file mode 100644
index f2ea950..0000000
--- a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
+++ /dev/null
@@ -1,932 +0,0 @@
-/*
- * Copyright (C) 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.server.telecom;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.IBluetoothHeadsetPhone;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.telecom.Connection;
-import android.telecom.Log;
-import android.telecom.PhoneAccount;
-import android.telecom.VideoProfile;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.telecom.CallsManager.CallsManagerListener;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Bluetooth headset manager for Telecom. This class shares the call state with the bluetooth device
- * and accepts call-related commands to perform on behalf of the BT device.
- */
-public class BluetoothPhoneServiceImpl {
-
-    public interface BluetoothPhoneServiceImplFactory {
-        BluetoothPhoneServiceImpl makeBluetoothPhoneServiceImpl(Context context,
-                TelecomSystem.SyncRoot lock, CallsManager callsManager,
-                PhoneAccountRegistrar phoneAccountRegistrar);
-    }
-
-    private static final String TAG = "BluetoothPhoneService";
-
-    // match up with bthf_call_state_t of bt_hf.h
-    private static final int CALL_STATE_ACTIVE = 0;
-    private static final int CALL_STATE_HELD = 1;
-    private static final int CALL_STATE_DIALING = 2;
-    private static final int CALL_STATE_ALERTING = 3;
-    private static final int CALL_STATE_INCOMING = 4;
-    private static final int CALL_STATE_WAITING = 5;
-    private static final int CALL_STATE_IDLE = 6;
-    private static final int CALL_STATE_DISCONNECTED = 7;
-
-    // match up with bthf_call_state_t of bt_hf.h
-    // Terminate all held or set UDUB("busy") to a waiting call
-    private static final int CHLD_TYPE_RELEASEHELD = 0;
-    // Terminate all active calls and accepts a waiting/held call
-    private static final int CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD = 1;
-    // Hold all active calls and accepts a waiting/held call
-    private static final int CHLD_TYPE_HOLDACTIVE_ACCEPTHELD = 2;
-    // Add all held calls to a conference
-    private static final int CHLD_TYPE_ADDHELDTOCONF = 3;
-
-    // Indicates that no call is ringing
-    private static final int DEFAULT_RINGING_ADDRESS_TYPE = 128;
-
-    private int mNumActiveCalls = 0;
-    private int mNumHeldCalls = 0;
-    private int mNumChildrenOfActiveCall = 0;
-    private int mBluetoothCallState = CALL_STATE_IDLE;
-    private String mRingingAddress = "";
-    private int mRingingAddressType = DEFAULT_RINGING_ADDRESS_TYPE;
-    private Call mOldHeldCall = null;
-    private boolean mIsDisconnectedTonePlaying = false;
-
-    /**
-     * Binder implementation of IBluetoothHeadsetPhone. Implements the command interface that the
-     * bluetooth headset code uses to control call.
-     */
-    @VisibleForTesting
-    public final IBluetoothHeadsetPhone.Stub mBinder = new IBluetoothHeadsetPhone.Stub() {
-        @Override
-        public boolean answerCall() throws RemoteException {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                Log.startSession("BPSI.aC");
-                long token = Binder.clearCallingIdentity();
-                try {
-                    Log.i(TAG, "BT - answering call");
-                    Call call = mCallsManager.getRingingOrSimulatedRingingCall();
-                    if (call != null) {
-                        mCallsManager.answerCall(call, VideoProfile.STATE_AUDIO_ONLY);
-                        return true;
-                    }
-                    return false;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                    Log.endSession();
-                }
-
-            }
-        }
-
-        @Override
-        public boolean hangupCall() throws RemoteException {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                Log.startSession("BPSI.hC");
-                long token = Binder.clearCallingIdentity();
-                try {
-                    Log.i(TAG, "BT - hanging up call");
-                    Call call = mCallsManager.getForegroundCall();
-                    if (call != null) {
-                        mCallsManager.disconnectCall(call);
-                        return true;
-                    }
-                    return false;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                    Log.endSession();
-                }
-            }
-        }
-
-        @Override
-        public boolean sendDtmf(int dtmf) throws RemoteException {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                Log.startSession("BPSI.sD");
-                long token = Binder.clearCallingIdentity();
-                try {
-                    Log.i(TAG, "BT - sendDtmf %c", Log.DEBUG ? dtmf : '.');
-                    Call call = mCallsManager.getForegroundCall();
-                    if (call != null) {
-                        // TODO: Consider making this a queue instead of starting/stopping
-                        // in quick succession.
-                        mCallsManager.playDtmfTone(call, (char) dtmf);
-                        mCallsManager.stopDtmfTone(call);
-                        return true;
-                    }
-                    return false;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                    Log.endSession();
-                }
-            }
-        }
-
-        @Override
-        public String getNetworkOperator() throws RemoteException {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                Log.startSession("BPSI.gNO");
-                long token = Binder.clearCallingIdentity();
-                try {
-                    Log.i(TAG, "getNetworkOperator");
-                    PhoneAccount account = getBestPhoneAccount();
-                    if (account != null && account.getLabel() != null) {
-                        return account.getLabel().toString();
-                    } else {
-                        // Finally, just get the network name from telephony.
-                        return mContext.getSystemService(TelephonyManager.class)
-                                .getNetworkOperatorName();
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                    Log.endSession();
-                }
-            }
-        }
-
-        @Override
-        public String getSubscriberNumber() throws RemoteException {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                Log.startSession("BPSI.gSN");
-                long token = Binder.clearCallingIdentity();
-                try {
-                    Log.i(TAG, "getSubscriberNumber");
-                    String address = null;
-                    PhoneAccount account = getBestPhoneAccount();
-                    if (account != null) {
-                        Uri addressUri = account.getAddress();
-                        if (addressUri != null) {
-                            address = addressUri.getSchemeSpecificPart();
-                        }
-                    }
-                    if (TextUtils.isEmpty(address)) {
-                        address = mContext.getSystemService(TelephonyManager.class)
-                                .getLine1Number();
-                        if (address == null) address = "";
-                    }
-                    return address;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                    Log.endSession();
-                }
-            }
-        }
-
-        @Override
-        public boolean listCurrentCalls() throws RemoteException {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                Log.startSession("BPSI.lCC");
-                long token = Binder.clearCallingIdentity();
-                try {
-                    // only log if it is after we recently updated the headset state or else it can
-                    // clog the android log since this can be queried every second.
-                    boolean logQuery = mHeadsetUpdatedRecently;
-                    mHeadsetUpdatedRecently = false;
-
-                    if (logQuery) {
-                        Log.i(TAG, "listcurrentCalls");
-                    }
-
-                    sendListOfCalls(logQuery);
-                    return true;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                    Log.endSession();
-                }
-            }
-        }
-
-        @Override
-        public boolean queryPhoneState() throws RemoteException {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                Log.startSession("BPSI.qPS");
-                long token = Binder.clearCallingIdentity();
-                try {
-                    Log.i(TAG, "queryPhoneState");
-                    updateHeadsetWithCallState(true /* force */);
-                    return true;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                    Log.endSession();
-                }
-            }
-        }
-
-        @Override
-        public boolean processChld(int chld) throws RemoteException {
-            synchronized (mLock) {
-                enforceModifyPermission();
-                Log.startSession("BPSI.pC");
-                long token = Binder.clearCallingIdentity();
-                try {
-                    Log.i(TAG, "processChld %d", chld);
-                    return BluetoothPhoneServiceImpl.this.processChld(chld);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                    Log.endSession();
-                }
-            }
-        }
-
-        @Override
-        public void updateBtHandsfreeAfterRadioTechnologyChange() throws RemoteException {
-            Log.d(TAG, "RAT change - deprecated");
-            // deprecated
-        }
-
-        @Override
-        public void cdmaSetSecondCallState(boolean state) throws RemoteException {
-            Log.d(TAG, "cdma 1 - deprecated");
-            // deprecated
-        }
-
-        @Override
-        public void cdmaSwapSecondCallState() throws RemoteException {
-            Log.d(TAG, "cdma 2 - deprecated");
-            // deprecated
-        }
-    };
-
-    /**
-     * Listens to call changes from the CallsManager and calls into methods to update the bluetooth
-     * headset with the new states.
-     */
-    @VisibleForTesting
-    public CallsManagerListener mCallsManagerListener = new CallsManagerListenerBase() {
-        @Override
-        public void onCallAdded(Call call) {
-            if (call.isExternalCall()) {
-                return;
-            }
-            updateHeadsetWithCallState(false /* force */);
-        }
-
-        @Override
-        public void onCallRemoved(Call call) {
-            if (call.isExternalCall()) {
-                return;
-            }
-            mClccIndexMap.remove(call);
-            updateHeadsetWithCallState(false /* force */);
-        }
-
-        /**
-         * Where a call which was external becomes a regular call, or a regular call becomes
-         * external, treat as an add or remove, respectively.
-         *
-         * @param call The call.
-         * @param isExternalCall {@code True} if the call became external, {@code false} otherwise.
-         */
-        @Override
-        public void onExternalCallChanged(Call call, boolean isExternalCall) {
-            if (isExternalCall) {
-                onCallRemoved(call);
-            } else {
-                onCallAdded(call);
-            }
-        }
-
-        @Override
-        public void onCallStateChanged(Call call, int oldState, int newState) {
-            if (call.isExternalCall()) {
-                return;
-            }
-            // If a call is being put on hold because of a new connecting call, ignore the
-            // CONNECTING since the BT state update needs to send out the numHeld = 1 + dialing
-            // state atomically.
-            // When the call later transitions to DIALING/DISCONNECTED we will then send out the
-            // aggregated update.
-            if (oldState == CallState.ACTIVE && newState == CallState.ON_HOLD) {
-                for (Call otherCall : mCallsManager.getCalls()) {
-                    if (otherCall.getState() == CallState.CONNECTING) {
-                        return;
-                    }
-                }
-            }
-
-            // To have an active call and another dialing at the same time is an invalid BT
-            // state. We can assume that the active call will be automatically held which will
-            // send another update at which point we will be in the right state.
-            if (mCallsManager.getActiveCall() != null
-                    && oldState == CallState.CONNECTING &&
-                    (newState == CallState.DIALING || newState == CallState.PULLING)) {
-                return;
-            }
-            updateHeadsetWithCallState(false /* force */);
-        }
-
-        @Override
-        public void onIsConferencedChanged(Call call) {
-            if (call.isExternalCall()) {
-                return;
-            }
-            /*
-             * Filter certain onIsConferencedChanged callbacks. Unfortunately this needs to be done
-             * because conference change events are not atomic and multiple callbacks get fired
-             * when two calls are conferenced together. This confuses updateHeadsetWithCallState
-             * if it runs in the middle of two calls being conferenced and can cause spurious and
-             * incorrect headset state updates. One of the scenarios is described below for CDMA
-             * conference calls.
-             *
-             * 1) Call 1 and Call 2 are being merged into conference Call 3.
-             * 2) Call 1 has its parent set to Call 3, but Call 2 does not have a parent yet.
-             * 3) updateHeadsetWithCallState now thinks that there are two active calls (Call 2 and
-             * Call 3) when there is actually only one active call (Call 3).
-             */
-            if (call.getParentCall() != null) {
-                // If this call is newly conferenced, ignore the callback. We only care about the
-                // one sent for the parent conference call.
-                Log.d(this, "Ignoring onIsConferenceChanged from child call with new parent");
-                return;
-            }
-            if (call.getChildCalls().size() == 1) {
-                // If this is a parent call with only one child, ignore the callback as well since
-                // the minimum number of child calls to start a conference call is 2. We expect
-                // this to be called again when the parent call has another child call added.
-                Log.d(this, "Ignoring onIsConferenceChanged from parent with only one child call");
-                return;
-            }
-            updateHeadsetWithCallState(false /* force */);
-        }
-
-        @Override
-        public void onDisconnectedTonePlaying(boolean isTonePlaying) {
-            mIsDisconnectedTonePlaying = isTonePlaying;
-            updateHeadsetWithCallState(false /* force */);
-        }
-    };
-
-    /**
-     * Listens to connections and disconnections of bluetooth headsets.  We need to save the current
-     * bluetooth headset so that we know where to send call updates.
-     */
-    @VisibleForTesting
-    public BluetoothProfile.ServiceListener mProfileListener =
-            new BluetoothProfile.ServiceListener() {
-                @Override
-                public void onServiceConnected(int profile, BluetoothProfile proxy) {
-                    synchronized (mLock) {
-                        setBluetoothHeadset(new BluetoothHeadsetProxy((BluetoothHeadset) proxy));
-                        updateHeadsetWithCallState(true /* force */);
-                    }
-                }
-
-                @Override
-                public void onServiceDisconnected(int profile) {
-                    synchronized (mLock) {
-                        mBluetoothHeadset = null;
-                    }
-                }
-            };
-
-    /**
-     * Receives events for global state changes of the bluetooth adapter.
-     */
-    @VisibleForTesting
-    public final BroadcastReceiver mBluetoothAdapterReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            synchronized (mLock) {
-                int state = intent
-                        .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
-                Log.d(TAG, "Bluetooth Adapter state: %d", state);
-                if (state == BluetoothAdapter.STATE_ON) {
-                    try {
-                        mBinder.queryPhoneState();
-                    } catch (RemoteException e) {
-                        // Remote exception not expected
-                    }
-                }
-            }
-        }
-    };
-
-    private BluetoothAdapterProxy mBluetoothAdapter;
-    private BluetoothHeadsetProxy mBluetoothHeadset;
-
-    // A map from Calls to indexes used to identify calls for CLCC (C* List Current Calls).
-    private Map<Call, Integer> mClccIndexMap = new HashMap<>();
-
-    private boolean mHeadsetUpdatedRecently = false;
-
-    private final Context mContext;
-    private final TelecomSystem.SyncRoot mLock;
-    private final CallsManager mCallsManager;
-    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
-
-    public IBinder getBinder() {
-        return mBinder;
-    }
-
-    public BluetoothPhoneServiceImpl(
-            Context context,
-            TelecomSystem.SyncRoot lock,
-            CallsManager callsManager,
-            BluetoothAdapterProxy bluetoothAdapter,
-            PhoneAccountRegistrar phoneAccountRegistrar) {
-        Log.d(this, "onCreate");
-
-        mContext = context;
-        mLock = lock;
-        mCallsManager = callsManager;
-        mPhoneAccountRegistrar = phoneAccountRegistrar;
-
-        mBluetoothAdapter = bluetoothAdapter;
-        if (mBluetoothAdapter == null) {
-            Log.d(this, "BluetoothPhoneService shutting down, no BT Adapter found.");
-            return;
-        }
-        mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
-
-        IntentFilter intentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
-        context.registerReceiver(mBluetoothAdapterReceiver, intentFilter);
-
-        mCallsManager.addListener(mCallsManagerListener);
-        updateHeadsetWithCallState(false /* force */);
-    }
-
-    @VisibleForTesting
-    public void setBluetoothHeadset(BluetoothHeadsetProxy bluetoothHeadset) {
-        mBluetoothHeadset = bluetoothHeadset;
-    }
-
-    private boolean processChld(int chld) {
-        Call activeCall = mCallsManager.getActiveCall();
-        Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
-        Call heldCall = mCallsManager.getHeldCall();
-
-        // TODO: Keeping as Log.i for now.  Move to Log.d after L release if BT proves stable.
-        Log.i(TAG, "Active: %s\nRinging: %s\nHeld: %s", activeCall, ringingCall, heldCall);
-
-        if (chld == CHLD_TYPE_RELEASEHELD) {
-            if (ringingCall != null) {
-                mCallsManager.rejectCall(ringingCall, false, null);
-                return true;
-            } else if (heldCall != null) {
-                mCallsManager.disconnectCall(heldCall);
-                return true;
-            }
-        } else if (chld == CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD) {
-            if (activeCall == null && ringingCall == null && heldCall == null)
-                return false;
-            if (activeCall != null) {
-                mCallsManager.disconnectCall(activeCall);
-                if (ringingCall != null) {
-                    mCallsManager.answerCall(ringingCall, VideoProfile.STATE_AUDIO_ONLY);
-                }
-                return true;
-            }
-            if (ringingCall != null) {
-                mCallsManager.answerCall(ringingCall, ringingCall.getVideoState());
-            } else if (heldCall != null) {
-                mCallsManager.unholdCall(heldCall);
-            }
-            return true;
-        } else if (chld == CHLD_TYPE_HOLDACTIVE_ACCEPTHELD) {
-            if (activeCall != null && activeCall.can(Connection.CAPABILITY_SWAP_CONFERENCE)) {
-                activeCall.swapConference();
-                Log.i(TAG, "CDMA calls in conference swapped, updating headset");
-                updateHeadsetWithCallState(true /* force */);
-                return true;
-            } else if (ringingCall != null) {
-                mCallsManager.answerCall(ringingCall, VideoProfile.STATE_AUDIO_ONLY);
-                return true;
-            } else if (heldCall != null) {
-                // CallsManager will hold any active calls when unhold() is called on a
-                // currently-held call.
-                mCallsManager.unholdCall(heldCall);
-                return true;
-            } else if (activeCall != null && activeCall.can(Connection.CAPABILITY_HOLD)) {
-                mCallsManager.holdCall(activeCall);
-                return true;
-            }
-        } else if (chld == CHLD_TYPE_ADDHELDTOCONF) {
-            if (activeCall != null) {
-                if (activeCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)) {
-                    activeCall.mergeConference();
-                    return true;
-                } else {
-                    List<Call> conferenceable = activeCall.getConferenceableCalls();
-                    if (!conferenceable.isEmpty()) {
-                        mCallsManager.conference(activeCall, conferenceable.get(0));
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    private void enforceModifyPermission() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MODIFY_PHONE_STATE, null);
-    }
-
-    private void sendListOfCalls(boolean shouldLog) {
-        Collection<Call> mCalls = mCallsManager.getCalls();
-        for (Call call : mCalls) {
-            // We don't send the parent conference call to the bluetooth device.
-            // We do, however want to send conferences that have no children to the bluetooth
-            // device (e.g. IMS Conference).
-            if (!call.isConference() ||
-                    (call.isConference() && call
-                            .can(Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN))) {
-                sendClccForCall(call, shouldLog);
-            }
-        }
-        sendClccEndMarker();
-    }
-
-    /**
-     * Sends a single clcc (C* List Current Calls) event for the specified call.
-     */
-    private void sendClccForCall(Call call, boolean shouldLog) {
-        boolean isForeground = mCallsManager.getForegroundCall() == call;
-        int state = getBtCallState(call, isForeground);
-        boolean isPartOfConference = false;
-        boolean isConferenceWithNoChildren = call.isConference() && call
-                .can(Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-
-        if (state == CALL_STATE_IDLE) {
-            return;
-        }
-
-        Call conferenceCall = call.getParentCall();
-        if (conferenceCall != null) {
-            isPartOfConference = true;
-
-            // Run some alternative states for Conference-level merge/swap support.
-            // Basically, if call supports swapping or merging at the conference-level, then we need
-            // to expose the calls as having distinct states (ACTIVE vs CAPABILITY_HOLD) or the
-            // functionality won't show up on the bluetooth device.
-
-            // Before doing any special logic, ensure that we are dealing with an ACTIVE call and
-            // that the conference itself has a notion of the current "active" child call.
-            Call activeChild = conferenceCall.getConferenceLevelActiveCall();
-            if (state == CALL_STATE_ACTIVE && activeChild != null) {
-                // Reevaluate state if we can MERGE or if we can SWAP without previously having
-                // MERGED.
-                boolean shouldReevaluateState =
-                        conferenceCall.can(Connection.CAPABILITY_MERGE_CONFERENCE) ||
-                        (conferenceCall.can(Connection.CAPABILITY_SWAP_CONFERENCE) &&
-                        !conferenceCall.wasConferencePreviouslyMerged());
-
-                if (shouldReevaluateState) {
-                    isPartOfConference = false;
-                    if (call == activeChild) {
-                        state = CALL_STATE_ACTIVE;
-                    } else {
-                        // At this point we know there is an "active" child and we know that it is
-                        // not this call, so set it to HELD instead.
-                        state = CALL_STATE_HELD;
-                    }
-                }
-            }
-            if (conferenceCall.getState() == CallState.ON_HOLD &&
-                    conferenceCall.can(Connection.CAPABILITY_MANAGE_CONFERENCE)) {
-                // If the parent IMS CEP conference call is on hold, we should mark this call as
-                // being on hold regardless of what the other children are doing.
-                state = CALL_STATE_HELD;
-            }
-        } else if (isConferenceWithNoChildren) {
-            // Handle the special case of an IMS conference call without conference event package
-            // support.  The call will be marked as a conference, but the conference will not have
-            // child calls where conference event packages are not used by the carrier.
-            isPartOfConference = true;
-        }
-
-        int index = getIndexForCall(call);
-        int direction = call.isIncoming() ? 1 : 0;
-        final Uri addressUri;
-        if (call.getGatewayInfo() != null) {
-            addressUri = call.getGatewayInfo().getOriginalAddress();
-        } else {
-            addressUri = call.getHandle();
-        }
-
-        String address = addressUri == null ? null : addressUri.getSchemeSpecificPart();
-        if (address != null) {
-            address = PhoneNumberUtils.stripSeparators(address);
-        }
-
-        int addressType = address == null ? -1 : PhoneNumberUtils.toaFromString(address);
-
-        if (shouldLog) {
-            Log.i(this, "sending clcc for call %d, %d, %d, %b, %s, %d",
-                    index, direction, state, isPartOfConference, Log.piiHandle(address),
-                    addressType);
-        }
-
-        if (mBluetoothHeadset != null) {
-            mBluetoothHeadset.clccResponse(
-                    index, direction, state, 0, isPartOfConference, address, addressType);
-        }
-    }
-
-    private void sendClccEndMarker() {
-        // End marker is recognized with an index value of 0. All other parameters are ignored.
-        if (mBluetoothHeadset != null) {
-            mBluetoothHeadset.clccResponse(0 /* index */, 0, 0, 0, false, null, 0);
-        }
-    }
-
-    /**
-     * Returns the caches index for the specified call.  If no such index exists, then an index is
-     * given (smallest number starting from 1 that isn't already taken).
-     */
-    private int getIndexForCall(Call call) {
-        if (mClccIndexMap.containsKey(call)) {
-            return mClccIndexMap.get(call);
-        }
-
-        int i = 1;  // Indexes for bluetooth clcc are 1-based.
-        while (mClccIndexMap.containsValue(i)) {
-            i++;
-        }
-
-        // NOTE: Indexes are removed in {@link #onCallRemoved}.
-        mClccIndexMap.put(call, i);
-        return i;
-    }
-
-    /**
-     * Sends an update of the current call state to the current Headset.
-     *
-     * @param force {@code true} if the headset state should be sent regardless if no changes to the
-     *      state have occurred, {@code false} if the state should only be sent if the state has
-     *      changed.
-     */
-    private void updateHeadsetWithCallState(boolean force) {
-        Call activeCall = mCallsManager.getActiveCall();
-        Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
-        Call heldCall = mCallsManager.getHeldCall();
-
-        int bluetoothCallState = getBluetoothCallStateForUpdate();
-
-        String ringingAddress = null;
-        int ringingAddressType = DEFAULT_RINGING_ADDRESS_TYPE;
-        String ringingName = null;
-        if (ringingCall != null && ringingCall.getHandle() != null
-            && !ringingCall.isSilentRingingRequested()) {
-            ringingAddress = ringingCall.getHandle().getSchemeSpecificPart();
-            if (ringingAddress != null) {
-                ringingAddressType = PhoneNumberUtils.toaFromString(ringingAddress);
-            }
-            ringingName = ringingCall.getCallerDisplayName();
-            if (TextUtils.isEmpty(ringingName)) {
-                ringingName = ringingCall.getName();
-            }
-        }
-        if (ringingAddress == null) {
-            ringingAddress = "";
-        }
-
-        int numActiveCalls = activeCall == null ? 0 : 1;
-        int numHeldCalls = mCallsManager.getNumHeldCalls();
-        int numChildrenOfActiveCall = activeCall == null ? 0 : activeCall.getChildCalls().size();
-
-        // Intermediate state for GSM calls which are in the process of being swapped.
-        // TODO: Should we be hardcoding this value to 2 or should we check if all top level calls
-        //       are held?
-        boolean callsPendingSwitch = (numHeldCalls == 2);
-
-        // For conference calls which support swapping the active call within the conference
-        // (namely CDMA calls) we need to expose that as a held call in order for the BT device
-        // to show "swap" and "merge" functionality.
-        boolean ignoreHeldCallChange = false;
-        if (activeCall != null && activeCall.isConference() &&
-                !activeCall.can(Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)) {
-            if (activeCall.can(Connection.CAPABILITY_SWAP_CONFERENCE)) {
-                // Indicate that BT device should show SWAP command by indicating that there is a
-                // call on hold, but only if the conference wasn't previously merged.
-                numHeldCalls = activeCall.wasConferencePreviouslyMerged() ? 0 : 1;
-            } else if (activeCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)) {
-                numHeldCalls = 1;  // Merge is available, so expose via numHeldCalls.
-            }
-
-            for (Call childCall : activeCall.getChildCalls()) {
-                // Held call has changed due to it being combined into a CDMA conference. Keep
-                // track of this and ignore any future update since it doesn't really count as
-                // a call change.
-                if (mOldHeldCall == childCall) {
-                    ignoreHeldCallChange = true;
-                    break;
-                }
-            }
-        }
-
-        if (mBluetoothHeadset != null &&
-                (force ||
-                        (!callsPendingSwitch &&
-                                (numActiveCalls != mNumActiveCalls ||
-                                        numChildrenOfActiveCall != mNumChildrenOfActiveCall ||
-                                        numHeldCalls != mNumHeldCalls ||
-                                        bluetoothCallState != mBluetoothCallState ||
-                                        !TextUtils.equals(ringingAddress, mRingingAddress) ||
-                                        ringingAddressType != mRingingAddressType ||
-                                (heldCall != mOldHeldCall && !ignoreHeldCallChange))))) {
-
-            // If the call is transitioning into the alerting state, send DIALING first.
-            // Some devices expect to see a DIALING state prior to seeing an ALERTING state
-            // so we need to send it first.
-            boolean sendDialingFirst = mBluetoothCallState != bluetoothCallState &&
-                    bluetoothCallState == CALL_STATE_ALERTING;
-
-            mOldHeldCall = heldCall;
-            mNumActiveCalls = numActiveCalls;
-            mNumChildrenOfActiveCall = numChildrenOfActiveCall;
-            mNumHeldCalls = numHeldCalls;
-            mBluetoothCallState = bluetoothCallState;
-            mRingingAddress = ringingAddress;
-            mRingingAddressType = ringingAddressType;
-
-            if (sendDialingFirst) {
-                // Log in full to make logs easier to debug.
-                Log.i(TAG, "updateHeadsetWithCallState " +
-                        "numActive %s, " +
-                        "numHeld %s, " +
-                        "callState %s, " +
-                        "ringing number %s, " +
-                        "ringing type %s, " +
-                        "ringing name %s",
-                        mNumActiveCalls,
-                        mNumHeldCalls,
-                        CALL_STATE_DIALING,
-                        Log.pii(mRingingAddress),
-                        mRingingAddressType,
-                        Log.pii(ringingName));
-                mBluetoothHeadset.phoneStateChanged(
-                        mNumActiveCalls,
-                        mNumHeldCalls,
-                        CALL_STATE_DIALING,
-                        mRingingAddress,
-                        mRingingAddressType,
-                        ringingName);
-            }
-
-            Log.i(TAG, "updateHeadsetWithCallState " +
-                    "numActive %s, " +
-                    "numHeld %s, " +
-                    "callState %s, " +
-                    "ringing number %s, " +
-                    "ringing type %s, " +
-                    "ringing name %s",
-                    mNumActiveCalls,
-                    mNumHeldCalls,
-                    mBluetoothCallState,
-                    Log.pii(mRingingAddress),
-                    mRingingAddressType,
-                    Log.pii(ringingName));
-
-            mBluetoothHeadset.phoneStateChanged(
-                    mNumActiveCalls,
-                    mNumHeldCalls,
-                    mBluetoothCallState,
-                    mRingingAddress,
-                    mRingingAddressType,
-                    ringingName);
-
-            mHeadsetUpdatedRecently = true;
-        }
-    }
-
-    private int getBluetoothCallStateForUpdate() {
-        Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
-        Call dialingCall = mCallsManager.getOutgoingCall();
-        boolean hasOnlyDisconnectedCalls = mCallsManager.hasOnlyDisconnectedCalls();
-
-        //
-        // !! WARNING !!
-        // You will note that CALL_STATE_WAITING, CALL_STATE_HELD, and CALL_STATE_ACTIVE are not
-        // used in this version of the call state mappings.  This is on purpose.
-        // phone_state_change() in btif_hf.c is not written to handle these states. Only with the
-        // listCalls*() method are WAITING and ACTIVE used.
-        // Using the unsupported states here caused problems with inconsistent state in some
-        // bluetooth devices (like not getting out of ringing state after answering a call).
-        //
-        int bluetoothCallState = CALL_STATE_IDLE;
-        if (ringingCall != null && !ringingCall.isSilentRingingRequested()) {
-            bluetoothCallState = CALL_STATE_INCOMING;
-        } else if (dialingCall != null) {
-            bluetoothCallState = CALL_STATE_ALERTING;
-        } else if (hasOnlyDisconnectedCalls || mIsDisconnectedTonePlaying) {
-            // Keep the DISCONNECTED state until the disconnect tone's playback is done
-            bluetoothCallState = CALL_STATE_DISCONNECTED;
-        }
-        return bluetoothCallState;
-    }
-
-    private int getBtCallState(Call call, boolean isForeground) {
-        switch (call.getState()) {
-            case CallState.NEW:
-            case CallState.ABORTED:
-            case CallState.DISCONNECTED:
-            case CallState.AUDIO_PROCESSING:
-                return CALL_STATE_IDLE;
-
-            case CallState.ACTIVE:
-                return CALL_STATE_ACTIVE;
-
-            case CallState.CONNECTING:
-            case CallState.SELECT_PHONE_ACCOUNT:
-            case CallState.DIALING:
-            case CallState.PULLING:
-                // Yes, this is correctly returning ALERTING.
-                // "Dialing" for BT means that we have sent information to the service provider
-                // to place the call but there is no confirmation that the call is going through.
-                // When there finally is confirmation, the ringback is played which is referred to
-                // as an "alert" tone, thus, ALERTING.
-                // TODO: We should consider using the ALERTING terms in Telecom because that
-                // seems to be more industry-standard.
-                return CALL_STATE_ALERTING;
-
-            case CallState.ON_HOLD:
-                return CALL_STATE_HELD;
-
-            case CallState.RINGING:
-            case CallState.ANSWERED:
-            case CallState.SIMULATED_RINGING:
-                if (call.isSilentRingingRequested()) {
-                    return CALL_STATE_IDLE;
-                } else if (isForeground) {
-                    return CALL_STATE_INCOMING;
-                } else {
-                    return CALL_STATE_WAITING;
-                }
-        }
-        return CALL_STATE_IDLE;
-    }
-
-    /**
-     * Returns the best phone account to use for the given state of all calls.
-     * First, tries to return the phone account for the foreground call, second the default
-     * phone account for PhoneAccount.SCHEME_TEL.
-     */
-    private PhoneAccount getBestPhoneAccount() {
-        if (mPhoneAccountRegistrar == null) {
-            return null;
-        }
-
-        Call call = mCallsManager.getForegroundCall();
-
-        PhoneAccount account = null;
-        if (call != null) {
-            // First try to get the network name of the foreground call.
-            account = mPhoneAccountRegistrar.getPhoneAccountOfCurrentUser(
-                    call.getTargetPhoneAccount());
-        }
-
-        if (account == null) {
-            // Second, Try to get the label for the default Phone Account.
-            account = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
-                    mPhoneAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
-                            PhoneAccount.SCHEME_TEL));
-        }
-        return account;
-    }
-}
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 08389b9..72c372a 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -27,7 +27,6 @@
 import com.android.server.telecom.ui.DisconnectedCallNotifier;
 import com.android.server.telecom.ui.IncomingCallNotifier;
 import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
-import com.android.server.telecom.BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory;
 import com.android.server.telecom.CallAudioManager.AudioServiceFactory;
 import com.android.server.telecom.DefaultDialerCache.DefaultDialerManagerAdapter;
 import com.android.server.telecom.ui.ToastFactory;
@@ -116,7 +115,6 @@
     private final CallsManager mCallsManager;
     private final RespondViaSmsManager mRespondViaSmsManager;
     private final Context mContext;
-    private final BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
     private final CallIntentProcessor mCallIntentProcessor;
     private final TelecomBroadcastIntentProcessor mTelecomBroadcastIntentProcessor;
     private final TelecomServiceImpl mTelecomServiceImpl;
@@ -193,8 +191,6 @@
             ProximitySensorManagerFactory proximitySensorManagerFactory,
             InCallWakeLockControllerFactory inCallWakeLockControllerFactory,
             AudioServiceFactory audioServiceFactory,
-            BluetoothPhoneServiceImplFactory
-                    bluetoothPhoneServiceImplFactory,
             ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory
                     connectionServiceFocusManagerFactory,
             Timeouts.Adapter timeoutsAdapter,
@@ -353,8 +349,6 @@
             mCallsManager.onUserSwitch(currentUserHandle);
         }
 
-        mBluetoothPhoneServiceImpl = bluetoothPhoneServiceImplFactory.makeBluetoothPhoneServiceImpl(
-                mContext, mLock, mCallsManager, mPhoneAccountRegistrar);
         mCallIntentProcessor = new CallIntentProcessor(mContext, mCallsManager, defaultDialerCache);
         mTelecomBroadcastIntentProcessor = new TelecomBroadcastIntentProcessor(
                 mContext, mCallsManager);
@@ -392,10 +386,6 @@
         return mCallsManager;
     }
 
-    public BluetoothPhoneServiceImpl getBluetoothPhoneServiceImpl() {
-        return mBluetoothPhoneServiceImpl;
-    }
-
     public CallIntentProcessor getCallIntentProcessor() {
         return mCallIntentProcessor;
     }
diff --git a/src/com/android/server/telecom/components/BluetoothPhoneService.java b/src/com/android/server/telecom/components/BluetoothPhoneService.java
deleted file mode 100644
index c5e195c..0000000
--- a/src/com/android/server/telecom/components/BluetoothPhoneService.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 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.server.telecom.components;
-
-import com.android.server.telecom.TelecomSystem;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-/**
- * Bluetooth headset manager for Telecom. This class shares the call state with the bluetooth device
- * and accepts call-related commands to perform on behalf of the BT device.
- */
-public final class BluetoothPhoneService extends Service implements TelecomSystem.Component {
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        synchronized (getTelecomSystem().getLock()) {
-            return getTelecomSystem().getBluetoothPhoneServiceImpl().getBinder();
-        }
-    }
-
-    @Override
-    public TelecomSystem getTelecomSystem() {
-        return TelecomSystem.getInstance();
-    }
-}
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index b6705f4..682990f 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -18,7 +18,6 @@
 
 import android.app.Service;
 import android.app.role.RoleManager;
-import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.Intent;
 import android.media.IAudioService;
@@ -35,8 +34,6 @@
 import com.android.internal.telecom.ITelecomLoader;
 import com.android.internal.telecom.ITelecomService;
 import com.android.server.telecom.AsyncRingtonePlayer;
-import com.android.server.telecom.BluetoothAdapterProxy;
-import com.android.server.telecom.BluetoothPhoneServiceImpl;
 import com.android.server.telecom.CallAudioModeStateMachine;
 import com.android.server.telecom.CallAudioRouteStateMachine;
 import com.android.server.telecom.CallerInfoAsyncQueryFactory;
@@ -173,17 +170,6 @@
                                             ServiceManager.getService(Context.AUDIO_SERVICE));
                                 }
                             },
-                            new BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory() {
-                                @Override
-                                public BluetoothPhoneServiceImpl makeBluetoothPhoneServiceImpl(
-                                        Context context, TelecomSystem.SyncRoot lock,
-                                        CallsManager callsManager,
-                                        PhoneAccountRegistrar phoneAccountRegistrar) {
-                                    return new BluetoothPhoneServiceImpl(context, lock,
-                                            callsManager, new BluetoothAdapterProxy(),
-                                            phoneAccountRegistrar);
-                                }
-                            },
                             ConnectionServiceFocusManager::new,
                             new Timeouts.Adapter(),
                             new AsyncRingtonePlayer(),
@@ -209,9 +195,6 @@
                             new ContactsAsyncHelper.Factory(),
                             internalServiceRetriever.getDeviceIdleController()));
         }
-        if (BluetoothAdapter.getDefaultAdapter() != null) {
-            context.startService(new Intent(context, BluetoothPhoneService.class));
-        }
     }
 
     @Override
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java b/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
deleted file mode 100644
index 532cc7e..0000000
--- a/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
+++ /dev/null
@@ -1,1136 +0,0 @@
-/*
- * Copyright (C) 2015 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.server.telecom.tests;
-
-import android.bluetooth.BluetoothAdapter;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.drawable.Icon;
-import android.net.Uri;
-import android.os.Binder;
-import android.telecom.Connection;
-import android.telecom.GatewayInfo;
-import android.telecom.PhoneAccount;
-import android.telecom.PhoneAccountHandle;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.server.telecom.BluetoothAdapterProxy;
-import com.android.server.telecom.BluetoothHeadsetProxy;
-import com.android.server.telecom.BluetoothPhoneServiceImpl;
-import com.android.server.telecom.Call;
-import com.android.server.telecom.CallState;
-import com.android.server.telecom.CallsManager;
-import com.android.server.telecom.PhoneAccountRegistrar;
-import com.android.server.telecom.TelecomSystem;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyChar;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
-
-@RunWith(JUnit4.class)
-public class BluetoothPhoneServiceTest extends TelecomTestCase {
-
-    private static final int TEST_DTMF_TONE = 0;
-    private static final String TEST_ACCOUNT_ADDRESS = "//foo.com/";
-    private static final int TEST_ACCOUNT_INDEX = 0;
-
-    // match up with BluetoothPhoneServiceImpl
-    private static final int CALL_STATE_ACTIVE = 0;
-    private static final int CALL_STATE_HELD = 1;
-    private static final int CALL_STATE_DIALING = 2;
-    private static final int CALL_STATE_ALERTING = 3;
-    private static final int CALL_STATE_INCOMING = 4;
-    private static final int CALL_STATE_WAITING = 5;
-    private static final int CALL_STATE_IDLE = 6;
-    private static final int CALL_STATE_DISCONNECTED = 7;
-    // Terminate all held or set UDUB("busy") to a waiting call
-    private static final int CHLD_TYPE_RELEASEHELD = 0;
-    // Terminate all active calls and accepts a waiting/held call
-    private static final int CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD = 1;
-    // Hold all active calls and accepts a waiting/held call
-    private static final int CHLD_TYPE_HOLDACTIVE_ACCEPTHELD = 2;
-    // Add all held calls to a conference
-    private static final int CHLD_TYPE_ADDHELDTOCONF = 3;
-
-    private BluetoothPhoneServiceImpl mBluetoothPhoneService;
-    private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {
-    };
-
-    @Mock CallsManager mMockCallsManager;
-    @Mock PhoneAccountRegistrar mMockPhoneAccountRegistrar;
-    @Mock BluetoothHeadsetProxy mMockBluetoothHeadset;
-
-    @Override
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        MockitoAnnotations.initMocks(this);
-        mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
-
-        // Ensure initialization does not actually try to access any of the CallsManager fields.
-        // This also works to return null if it is not overwritten later in the test.
-        doNothing().when(mMockCallsManager).addListener(any(
-                CallsManager.CallsManagerListener.class));
-        doReturn(null).when(mMockCallsManager).getActiveCall();
-        doReturn(null).when(mMockCallsManager).getRingingOrSimulatedRingingCall();
-        doReturn(null).when(mMockCallsManager).getHeldCall();
-        doReturn(null).when(mMockCallsManager).getOutgoingCall();
-        doReturn(0).when(mMockCallsManager).getNumHeldCalls();
-        doReturn(false).when(mMockCallsManager).hasOnlyDisconnectedCalls();
-        mBluetoothPhoneService = new BluetoothPhoneServiceImpl(mContext, mLock, mMockCallsManager,
-                mock(BluetoothAdapterProxy.class), mMockPhoneAccountRegistrar);
-
-        // Bring in test Bluetooth Headset
-        mBluetoothPhoneService.setBluetoothHeadset(mMockBluetoothHeadset);
-    }
-
-    @Override
-    @After
-    public void tearDown() throws Exception {
-
-        mBluetoothPhoneService = null;
-        super.tearDown();
-    }
-
-    @SmallTest
-    @Test
-    public void testHeadsetAnswerCall() throws Exception {
-        Call mockCall = createRingingCall();
-
-        boolean callAnswered = mBluetoothPhoneService.mBinder.answerCall();
-
-        verify(mMockCallsManager).answerCall(eq(mockCall), any(int.class));
-        assertEquals(callAnswered, true);
-    }
-
-    @SmallTest
-    @Test
-    public void testHeadsetAnswerCallNull() throws Exception {
-        when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
-
-        boolean callAnswered = mBluetoothPhoneService.mBinder.answerCall();
-
-        verify(mMockCallsManager,never()).answerCall(any(Call.class), any(int.class));
-        assertEquals(callAnswered, false);
-    }
-
-    @SmallTest
-    @Test
-    public void testHeadsetHangupCall() throws Exception {
-        Call mockCall = createForegroundCall();
-
-        boolean callHungup = mBluetoothPhoneService.mBinder.hangupCall();
-
-        verify(mMockCallsManager).disconnectCall(eq(mockCall));
-        assertEquals(callHungup, true);
-    }
-
-    @SmallTest
-    @Test
-    public void testHeadsetHangupCallNull() throws Exception {
-        when(mMockCallsManager.getForegroundCall()).thenReturn(null);
-
-        boolean callHungup = mBluetoothPhoneService.mBinder.hangupCall();
-
-        verify(mMockCallsManager,never()).disconnectCall(any(Call.class));
-        assertEquals(callHungup, false);
-    }
-
-    @SmallTest
-    @Test
-    public void testHeadsetSendDTMF() throws Exception {
-        Call mockCall = createForegroundCall();
-
-        boolean sentDtmf = mBluetoothPhoneService.mBinder.sendDtmf(TEST_DTMF_TONE);
-
-        verify(mMockCallsManager).playDtmfTone(eq(mockCall), eq((char) TEST_DTMF_TONE));
-        verify(mMockCallsManager).stopDtmfTone(eq(mockCall));
-        assertEquals(sentDtmf, true);
-    }
-
-    @SmallTest
-    @Test
-    public void testHeadsetSendDTMFNull() throws Exception {
-        when(mMockCallsManager.getForegroundCall()).thenReturn(null);
-
-        boolean sentDtmf = mBluetoothPhoneService.mBinder.sendDtmf(TEST_DTMF_TONE);
-
-        verify(mMockCallsManager,never()).playDtmfTone(any(Call.class), anyChar());
-        verify(mMockCallsManager,never()).stopDtmfTone(any(Call.class));
-        assertEquals(sentDtmf, false);
-    }
-
-    @SmallTest
-    @Test
-    public void testGetNetworkOperator() throws Exception {
-        Call mockCall = createForegroundCall();
-        PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX);
-        when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser(
-                nullable(PhoneAccountHandle.class))).thenReturn(fakePhoneAccount);
-
-        String networkOperator = mBluetoothPhoneService.mBinder.getNetworkOperator();
-
-        assertEquals(networkOperator, "label0");
-    }
-
-    @SmallTest
-    @Test
-    public void testGetNetworkOperatorNoPhoneAccount() throws Exception {
-        when(mMockCallsManager.getForegroundCall()).thenReturn(null);
-
-        String networkOperator = mBluetoothPhoneService.mBinder.getNetworkOperator();
-
-        assertEquals(networkOperator, "label1");
-    }
-
-    @SmallTest
-    @Test
-    public void testGetSubscriberNumber() throws Exception {
-        Call mockCall = createForegroundCall();
-        PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX);
-        when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser(
-                nullable(PhoneAccountHandle.class))).thenReturn(fakePhoneAccount);
-
-        String subscriberNumber = mBluetoothPhoneService.mBinder.getSubscriberNumber();
-
-        assertEquals(subscriberNumber, TEST_ACCOUNT_ADDRESS + TEST_ACCOUNT_INDEX);
-    }
-
-    @SmallTest
-    @Test
-    public void testGetSubscriberNumberFallbackToTelephony() throws Exception {
-        Call mockCall = createForegroundCall();
-        String fakeNumber = "8675309";
-        when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser(
-                nullable(PhoneAccountHandle.class))).thenReturn(null);
-        when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(
-                nullable(PhoneAccountHandle.class))).thenReturn(null);
-        when(mComponentContextFixture.getTelephonyManager().getLine1Number())
-                .thenReturn(fakeNumber);
-
-        String subscriberNumber = mBluetoothPhoneService.mBinder.getSubscriberNumber();
-
-        assertEquals(subscriberNumber, fakeNumber);
-    }
-
-    @MediumTest
-    @Test
-    public void testListCurrentCallsOneCall() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        Call activeCall = createActiveCall();
-        when(activeCall.getState()).thenReturn(CallState.ACTIVE);
-        calls.add(activeCall);
-        when(activeCall.isConference()).thenReturn(false);
-        when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-000"));
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-
-        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(0), eq(0), eq(false),
-                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown));
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-    }
-
-    @MediumTest
-    @Test
-    public void testListCurrentCallsSilentRinging() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        Call silentRingingCall = createActiveCall();
-        when(silentRingingCall.getState()).thenReturn(CallState.RINGING);
-        when(silentRingingCall.isSilentRingingRequested()).thenReturn(true);
-        calls.add(silentRingingCall);
-        when(silentRingingCall.isConference()).thenReturn(false);
-        when(silentRingingCall.getHandle()).thenReturn(Uri.parse("tel:555-000"));
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(silentRingingCall);
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-
-        verify(mMockBluetoothHeadset, never()).clccResponse(eq(1), eq(0), eq(0), eq(0), eq(false),
-            eq("555000"), eq(PhoneNumberUtils.TOA_Unknown));
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-    }
-
-    @MediumTest
-    @Test
-    public void testConferenceInProgressCDMA() throws Exception {
-        // If two calls are being conferenced and updateHeadsetWithCallState runs while this is
-        // still occuring, it will look like there is an active and held call still while we are
-        // transitioning into a conference.
-        // Call has been put into a CDMA "conference" with one call on hold.
-        ArrayList<Call> calls = new ArrayList<>();
-        Call parentCall = createActiveCall();
-        final Call confCall1 = mock(Call.class);
-        final Call confCall2 = createHeldCall();
-        calls.add(parentCall);
-        calls.add(confCall1);
-        calls.add(confCall2);
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        when(confCall1.getState()).thenReturn(CallState.ACTIVE);
-        when(confCall2.getState()).thenReturn(CallState.ACTIVE);
-        when(confCall1.isIncoming()).thenReturn(false);
-        when(confCall2.isIncoming()).thenReturn(true);
-        when(confCall1.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0000")));
-        when(confCall2.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0001")));
-        addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-        addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
-        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentCall.getConferenceLevelActiveCall()).thenReturn(confCall1);
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
-            add(confCall1);
-            add(confCall2);
-        }});
-        //Add links from child calls to parent
-        when(confCall1.getParentCall()).thenReturn(parentCall);
-        when(confCall2.getParentCall()).thenReturn(parentCall);
-
-        mBluetoothPhoneService.mBinder.queryPhoneState();
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true);
-        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-        when(mMockCallsManager.getHeldCall()).thenReturn(null);
-        // Spurious call to onIsConferencedChanged.
-        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
-        // Make sure the call has only occurred collectively 2 times (not on the third)
-        verify(mMockBluetoothHeadset, times(2)).phoneStateChanged(any(int.class),
-                any(int.class), any(int.class), nullable(String.class), any(int.class),
-                nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testListCurrentCallsCdmaHold() throws Exception {
-        // Call has been put into a CDMA "conference" with one call on hold.
-        ArrayList<Call> calls = new ArrayList<>();
-        Call parentCall = createActiveCall();
-        final Call foregroundCall = mock(Call.class);
-        final Call heldCall = createHeldCall();
-        calls.add(parentCall);
-        calls.add(foregroundCall);
-        calls.add(heldCall);
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        when(foregroundCall.getState()).thenReturn(CallState.ACTIVE);
-        when(heldCall.getState()).thenReturn(CallState.ACTIVE);
-        when(foregroundCall.isIncoming()).thenReturn(false);
-        when(heldCall.isIncoming()).thenReturn(true);
-        when(foregroundCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0000")));
-        when(heldCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0001")));
-        addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-        addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
-        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentCall.getConferenceLevelActiveCall()).thenReturn(foregroundCall);
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
-            add(foregroundCall);
-            add(heldCall);
-        }});
-        //Add links from child calls to parent
-        when(foregroundCall.getParentCall()).thenReturn(parentCall);
-        when(heldCall.getParentCall()).thenReturn(parentCall);
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-
-        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0),
-                eq(false), eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
-        verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_HELD), eq(0),
-                eq(false), eq("5550001"), eq(PhoneNumberUtils.TOA_Unknown));
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-    }
-
-    @MediumTest
-    @Test
-    public void testListCurrentCallsCdmaConference() throws Exception {
-        // Call is in a true CDMA conference
-        ArrayList<Call> calls = new ArrayList<>();
-        Call parentCall = createActiveCall();
-        final Call confCall1 = mock(Call.class);
-        final Call confCall2 = createHeldCall();
-        calls.add(parentCall);
-        calls.add(confCall1);
-        calls.add(confCall2);
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        when(confCall1.getState()).thenReturn(CallState.ACTIVE);
-        when(confCall2.getState()).thenReturn(CallState.ACTIVE);
-        when(confCall1.isIncoming()).thenReturn(false);
-        when(confCall2.isIncoming()).thenReturn(true);
-        when(confCall1.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0000")));
-        when(confCall2.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0001")));
-        removeCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true);
-        when(parentCall.getConferenceLevelActiveCall()).thenReturn(confCall1);
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
-            add(confCall1);
-            add(confCall2);
-        }});
-        //Add links from child calls to parent
-        when(confCall1.getParentCall()).thenReturn(parentCall);
-        when(confCall2.getParentCall()).thenReturn(parentCall);
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-
-        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0),
-                eq(true), eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
-        verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_ACTIVE), eq(0),
-                eq(true), eq("5550001"), eq(PhoneNumberUtils.TOA_Unknown));
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-    }
-
-    @MediumTest
-    @Test
-    public void testWaitingCallClccResponse() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        // This test does not define a value for getForegroundCall(), so this ringing call will
-        // be treated as if it is a waiting call when listCurrentCalls() is invoked.
-        Call waitingCall = createRingingCall();
-        calls.add(waitingCall);
-        when(waitingCall.isIncoming()).thenReturn(true);
-        when(waitingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0000")));
-        when(waitingCall.getState()).thenReturn(CallState.RINGING);
-        when(waitingCall.isConference()).thenReturn(false);
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_WAITING, 0, false,
-                "5550000", PhoneNumberUtils.TOA_Unknown);
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-        verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(),
-                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
-    }
-
-    @MediumTest
-    @Test
-    public void testNewCallClccResponse() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        Call newCall = createForegroundCall();
-        calls.add(newCall);
-        when(newCall.getState()).thenReturn(CallState.NEW);
-        when(newCall.isConference()).thenReturn(false);
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-        verify(mMockBluetoothHeadset, times(1)).clccResponse(anyInt(),
-                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
-    }
-
-    @MediumTest
-    @Test
-    public void testRingingCallClccResponse() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        Call ringingCall = createForegroundCall();
-        calls.add(ringingCall);
-        when(ringingCall.getState()).thenReturn(CallState.RINGING);
-        when(ringingCall.isIncoming()).thenReturn(true);
-        when(ringingCall.isConference()).thenReturn(false);
-        when(ringingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0000")));
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false,
-                "5550000", PhoneNumberUtils.TOA_Unknown);
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-        verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(),
-                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
-    }
-
-    @MediumTest
-    @Test
-    public void testCallClccCache() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        Call ringingCall = createForegroundCall();
-        calls.add(ringingCall);
-        when(ringingCall.getState()).thenReturn(CallState.RINGING);
-        when(ringingCall.isIncoming()).thenReturn(true);
-        when(ringingCall.isConference()).thenReturn(false);
-        when(ringingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:5550000")));
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false,
-                "5550000", PhoneNumberUtils.TOA_Unknown);
-
-        // Test Caching of old call indicies in clcc
-        when(ringingCall.getState()).thenReturn(CallState.ACTIVE);
-        Call newHoldingCall = createHeldCall();
-        calls.add(0, newHoldingCall);
-        when(newHoldingCall.getState()).thenReturn(CallState.ON_HOLD);
-        when(newHoldingCall.isIncoming()).thenReturn(true);
-        when(newHoldingCall.isConference()).thenReturn(false);
-        when(newHoldingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0001")));
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_ACTIVE, 0, false,
-                "5550000", PhoneNumberUtils.TOA_Unknown);
-        verify(mMockBluetoothHeadset).clccResponse(2, 1, CALL_STATE_HELD, 0, false,
-                "5550001", PhoneNumberUtils.TOA_Unknown);
-        verify(mMockBluetoothHeadset, times(2)).clccResponse(0, 0, 0, 0, false, null, 0);
-    }
-
-    @MediumTest
-    @Test
-    public void testAlertingCallClccResponse() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        Call dialingCall = createForegroundCall();
-        calls.add(dialingCall);
-        when(dialingCall.getState()).thenReturn(CallState.DIALING);
-        when(dialingCall.isIncoming()).thenReturn(false);
-        when(dialingCall.isConference()).thenReturn(false);
-        when(dialingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0000")));
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-        verify(mMockBluetoothHeadset).clccResponse(1, 0, CALL_STATE_ALERTING, 0, false,
-                "5550000", PhoneNumberUtils.TOA_Unknown);
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-        verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(),
-                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
-    }
-
-    @MediumTest
-    @Test
-    public void testHoldingCallClccResponse() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-        Call dialingCall = createForegroundCall();
-        calls.add(dialingCall);
-        when(dialingCall.getState()).thenReturn(CallState.DIALING);
-        when(dialingCall.isIncoming()).thenReturn(false);
-        when(dialingCall.isConference()).thenReturn(false);
-        when(dialingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0000")));
-        Call holdingCall = createHeldCall();
-        calls.add(holdingCall);
-        when(holdingCall.getState()).thenReturn(CallState.ON_HOLD);
-        when(holdingCall.isIncoming()).thenReturn(true);
-        when(holdingCall.isConference()).thenReturn(false);
-        when(holdingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
-                Uri.parse("tel:555-0001")));
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-        verify(mMockBluetoothHeadset).clccResponse(1, 0, CALL_STATE_ALERTING, 0, false,
-                "5550000", PhoneNumberUtils.TOA_Unknown);
-        verify(mMockBluetoothHeadset).clccResponse(2, 1, CALL_STATE_HELD, 0, false,
-                "5550001", PhoneNumberUtils.TOA_Unknown);
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-        verify(mMockBluetoothHeadset, times(3)).clccResponse(anyInt(),
-                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
-    }
-
-    @MediumTest
-    @Test
-    public void testListCurrentCallsImsConference() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        Call parentCall = createActiveCall();
-        calls.add(parentCall);
-        addCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.getState()).thenReturn(CallState.ACTIVE);
-        when(parentCall.isIncoming()).thenReturn(true);
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-
-        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(1), eq(CALL_STATE_ACTIVE), eq(0),
-                eq(true), (String) isNull(), eq(-1));
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-    }
-
-    @MediumTest
-    @Test
-    public void testListCurrentCallsHeldImsCepConference() throws Exception {
-        ArrayList<Call> calls = new ArrayList<>();
-        Call parentCall = createHeldCall();
-        Call childCall1 = createActiveCall();
-        Call childCall2 = createActiveCall();
-        calls.add(parentCall);
-        calls.add(childCall1);
-        calls.add(childCall2);
-        addCallCapability(parentCall, Connection.CAPABILITY_MANAGE_CONFERENCE);
-        when(childCall1.getParentCall()).thenReturn(parentCall);
-        when(childCall2.getParentCall()).thenReturn(parentCall);
-
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.getState()).thenReturn(CallState.ON_HOLD);
-        when(childCall1.getState()).thenReturn(CallState.ACTIVE);
-        when(childCall2.getState()).thenReturn(CallState.ACTIVE);
-
-        when(parentCall.isIncoming()).thenReturn(true);
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-
-        mBluetoothPhoneService.mBinder.listCurrentCalls();
-
-        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_HELD), eq(0),
-                eq(true), (String) isNull(), eq(-1));
-        verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(0), eq(CALL_STATE_HELD), eq(0),
-                eq(true), (String) isNull(), eq(-1));
-        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
-    }
-
-    @MediumTest
-    @Test
-    public void testQueryPhoneState() throws Exception {
-        Call ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:5550000"));
-
-        mBluetoothPhoneService.mBinder.queryPhoneState();
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testCDMAConferenceQueryState() throws Exception {
-        Call parentConfCall = createActiveCall();
-        final Call confCall1 = mock(Call.class);
-        final Call confCall2 = mock(Call.class);
-        when(parentConfCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
-        addCallCapability(parentConfCall, Connection.CAPABILITY_SWAP_CONFERENCE);
-        removeCallCapability(parentConfCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentConfCall.wasConferencePreviouslyMerged()).thenReturn(true);
-        when(parentConfCall.isConference()).thenReturn(true);
-        when(parentConfCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
-            add(confCall1);
-            add(confCall2);
-        }});
-
-        mBluetoothPhoneService.mBinder.queryPhoneState();
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldTypeReleaseHeldRinging() throws Exception {
-        Call ringingCall = createRingingCall();
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_RELEASEHELD);
-
-        verify(mMockCallsManager).rejectCall(eq(ringingCall), eq(false), nullable(String.class));
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldTypeReleaseHeldHold() throws Exception {
-        Call onHoldCall = createHeldCall();
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_RELEASEHELD);
-
-        verify(mMockCallsManager).disconnectCall(eq(onHoldCall));
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldReleaseActiveRinging() throws Exception {
-        Call activeCall = createActiveCall();
-        Call ringingCall = createRingingCall();
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
-                CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD);
-
-        verify(mMockCallsManager).disconnectCall(eq(activeCall));
-        verify(mMockCallsManager).answerCall(eq(ringingCall), any(int.class));
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldReleaseActiveHold() throws Exception {
-        Call activeCall = createActiveCall();
-        Call heldCall = createHeldCall();
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
-                CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD);
-
-        verify(mMockCallsManager).disconnectCall(eq(activeCall));
-        // Call unhold will occur as part of CallsManager auto-unholding the background call on its
-        // own.
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldHoldActiveRinging() throws Exception {
-        Call ringingCall = createRingingCall();
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
-                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
-
-        verify(mMockCallsManager).answerCall(eq(ringingCall), any(int.class));
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldHoldActiveUnhold() throws Exception {
-        Call heldCall = createHeldCall();
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
-                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
-
-        verify(mMockCallsManager).unholdCall(eq(heldCall));
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldHoldActiveHold() throws Exception {
-        Call activeCall = createActiveCall();
-        addCallCapability(activeCall, Connection.CAPABILITY_HOLD);
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
-                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
-
-        verify(mMockCallsManager).holdCall(eq(activeCall));
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldAddHeldToConfHolding() throws Exception {
-        Call activeCall = createActiveCall();
-        addCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_ADDHELDTOCONF);
-
-        verify(activeCall).mergeConference();
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldAddHeldToConf() throws Exception {
-        Call activeCall = createActiveCall();
-        removeCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-        Call conferenceableCall = mock(Call.class);
-        ArrayList<Call> conferenceableCalls = new ArrayList<>();
-        conferenceableCalls.add(conferenceableCall);
-        when(activeCall.getConferenceableCalls()).thenReturn(conferenceableCalls);
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_ADDHELDTOCONF);
-
-        verify(mMockCallsManager).conference(activeCall, conferenceableCall);
-        assertEquals(didProcess, true);
-    }
-
-    @MediumTest
-    @Test
-    public void testProcessChldHoldActiveSwapConference() throws Exception {
-        // Create an active CDMA Call with a call on hold and simulate a swapConference().
-        Call parentCall = createActiveCall();
-        final Call foregroundCall = mock(Call.class);
-        final Call heldCall = createHeldCall();
-        addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
-        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false);
-        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
-            add(foregroundCall);
-            add(heldCall);
-        }});
-
-        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
-                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
-
-        verify(parentCall).swapConference();
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), eq(""),
-                eq(128), nullable(String.class));
-        assertEquals(didProcess, true);
-    }
-
-    // Testing the CallsManager Listener Functionality on Bluetooth
-    @MediumTest
-    @Test
-    public void testOnCallAddedRinging() throws Exception {
-        Call ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testSilentRingingCallState() throws Exception {
-        Call ringingCall = createRingingCall();
-        when(ringingCall.isSilentRingingRequested()).thenReturn(true);
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallAddedCdmaActiveHold() throws Exception {
-        // Call has been put into a CDMA "conference" with one call on hold.
-        Call parentCall = createActiveCall();
-        final Call foregroundCall = mock(Call.class);
-        final Call heldCall = createHeldCall();
-        addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
-            add(foregroundCall);
-            add(heldCall);
-        }});
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(parentCall);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallRemoved() throws Exception {
-        Call activeCall = createActiveCall();
-        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(activeCall);
-        doReturn(null).when(mMockCallsManager).getActiveCall();
-        mBluetoothPhoneService.mCallsManagerListener.onCallRemoved(activeCall);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChangedConnectingCall() throws Exception {
-        Call activeCall = mock(Call.class);
-        Call connectingCall = mock(Call.class);
-        when(connectingCall.getState()).thenReturn(CallState.CONNECTING);
-        ArrayList<Call> calls = new ArrayList<>();
-        calls.add(connectingCall);
-        calls.add(activeCall);
-        when(mMockCallsManager.getCalls()).thenReturn(calls);
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall,
-                CallState.ACTIVE, CallState.ON_HOLD);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallAddedAudioProcessing() throws Exception {
-        Call call = mock(Call.class);
-        when(call.getState()).thenReturn(CallState.AUDIO_PROCESSING);
-        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(call);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChangedRingingToAudioProcessing() throws Exception {
-        Call ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-
-        when(ringingCall.getState()).thenReturn(CallState.AUDIO_PROCESSING);
-        when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
-                CallState.RINGING, CallState.AUDIO_PROCESSING);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChangedAudioProcessingToSimulatedRinging() throws Exception {
-        Call ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
-                CallState.AUDIO_PROCESSING, CallState.SIMULATED_RINGING);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChangedAudioProcessingToActive() throws Exception {
-        Call activeCall = createActiveCall();
-        when(activeCall.getState()).thenReturn(CallState.ACTIVE);
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall,
-                CallState.AUDIO_PROCESSING, CallState.ACTIVE);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChangedDialing() throws Exception {
-        Call activeCall = createActiveCall();
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall,
-                CallState.CONNECTING, CallState.DIALING);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChangedAlerting() throws Exception {
-        Call outgoingCall = createOutgoingCall();
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(outgoingCall,
-                CallState.NEW, CallState.DIALING);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DIALING),
-                eq(""), eq(128), nullable(String.class));
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_ALERTING),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChangedDisconnected() throws Exception {
-        Call disconnectedCall = createDisconnectedCall();
-        doReturn(true).when(mMockCallsManager).hasOnlyDisconnectedCalls();
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(disconnectedCall,
-                CallState.DISCONNECTING, CallState.DISCONNECTED);
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
-                eq(""), eq(128), nullable(String.class));
-
-        doReturn(false).when(mMockCallsManager).hasOnlyDisconnectedCalls();
-        mBluetoothPhoneService.mCallsManagerListener.onDisconnectedTonePlaying(true);
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
-                eq(""), eq(128), nullable(String.class));
-
-        mBluetoothPhoneService.mCallsManagerListener.onDisconnectedTonePlaying(false);
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChanged() throws Exception {
-        Call ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
-        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-
-        //Switch to active
-        doReturn(null).when(mMockCallsManager).getRingingOrSimulatedRingingCall();
-        when(mMockCallsManager.getActiveCall()).thenReturn(ringingCall);
-
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
-                CallState.RINGING, CallState.ACTIVE);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnCallStateChangedGSMSwap() throws Exception {
-        Call heldCall = createHeldCall();
-        when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
-        doReturn(2).when(mMockCallsManager).getNumHeldCalls();
-        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(heldCall,
-                CallState.ACTIVE, CallState.ON_HOLD);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(eq(0), eq(2), eq(CALL_STATE_HELD),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testOnIsConferencedChanged() throws Exception {
-        // Start with two calls that are being merged into a CDMA conference call. The
-        // onIsConferencedChanged method will be called multiple times during the call. Make sure
-        // that the bluetooth phone state is updated properly.
-        Call parentCall = createActiveCall();
-        Call activeCall = mock(Call.class);
-        Call heldCall = createHeldCall();
-        when(activeCall.getParentCall()).thenReturn(parentCall);
-        when(heldCall.getParentCall()).thenReturn(parentCall);
-        ArrayList<Call> calls = new ArrayList<>();
-        calls.add(activeCall);
-        when(parentCall.getChildCalls()).thenReturn(calls);
-        when(parentCall.isConference()).thenReturn(true);
-        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
-        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false);
-
-        // Be sure that onIsConferencedChanged rejects spurious changes during set up of
-        // CDMA "conference"
-        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(activeCall);
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(heldCall);
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-
-        calls.add(heldCall);
-        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @MediumTest
-    @Test
-    public void testBluetoothAdapterReceiver() throws Exception {
-        Call ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:5550000"));
-
-        Intent intent = new Intent();
-        intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON);
-        mBluetoothPhoneService.mBluetoothAdapterReceiver.onReceive(mContext, intent);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    private void addCallCapability(Call call, int capability) {
-        when(call.can(capability)).thenReturn(true);
-    }
-
-    private void removeCallCapability(Call call, int capability) {
-        when(call.can(capability)).thenReturn(false);
-    }
-
-    private Call createActiveCall() {
-        Call call = mock(Call.class);
-        when(mMockCallsManager.getActiveCall()).thenReturn(call);
-        return call;
-    }
-
-    private Call createRingingCall() {
-        Call call = mock(Call.class);
-        when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(call);
-        return call;
-    }
-
-    private Call createHeldCall() {
-        Call call = mock(Call.class);
-        when(mMockCallsManager.getHeldCall()).thenReturn(call);
-        return call;
-    }
-
-    private Call createOutgoingCall() {
-        Call call = mock(Call.class);
-        when(mMockCallsManager.getOutgoingCall()).thenReturn(call);
-        return call;
-    }
-
-    private Call createDisconnectedCall() {
-        Call call = mock(Call.class);
-        when(mMockCallsManager.getFirstCallWithState(CallState.DISCONNECTED)).thenReturn(call);
-        return call;
-    }
-
-    private Call createForegroundCall() {
-        Call call = mock(Call.class);
-        when(mMockCallsManager.getForegroundCall()).thenReturn(call);
-        return call;
-    }
-
-    private static ComponentName makeQuickConnectionServiceComponentName() {
-        return new ComponentName("com.android.server.telecom.tests",
-                "com.android.server.telecom.tests.MockConnectionService");
-    }
-
-    private static PhoneAccountHandle makeQuickAccountHandle(String id) {
-        return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id,
-                Binder.getCallingUserHandle());
-    }
-
-    private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
-        return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx);
-    }
-
-    private PhoneAccount makeQuickAccount(String id, int idx) {
-        return makeQuickAccountBuilder(id, idx)
-                .setAddress(Uri.parse(TEST_ACCOUNT_ADDRESS + idx))
-                .setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
-                .setCapabilities(idx)
-                .setIcon(Icon.createWithResource(
-                        "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
-                .setShortDescription("desc" + idx)
-                .setIsEnabled(true)
-                .build();
-    }
-}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index aeb68c5..ab7693a 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -69,7 +69,6 @@
 
 import com.android.internal.telecom.IInCallAdapter;
 import com.android.server.telecom.AsyncRingtonePlayer;
-import com.android.server.telecom.BluetoothPhoneServiceImpl;
 import com.android.server.telecom.CallAudioManager;
 import com.android.server.telecom.CallAudioModeStateMachine;
 import com.android.server.telecom.CallAudioRouteStateMachine;
@@ -203,7 +202,6 @@
     @Mock HeadsetMediaButton mHeadsetMediaButton;
     @Mock ProximitySensorManager mProximitySensorManager;
     @Mock InCallWakeLockController mInCallWakeLockController;
-    @Mock BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
     @Mock AsyncRingtonePlayer mAsyncRingtonePlayer;
     @Mock IncomingCallNotifier mIncomingCallNotifier;
     @Mock ClockProxy mClockProxy;
@@ -487,7 +485,6 @@
                 proximitySensorManagerFactory,
                 inCallWakeLockControllerFactory,
                 () -> mAudioService,
-                (context, lock, callsManager, phoneAccountRegistrar) -> mBluetoothPhoneServiceImpl,
                 mConnServFMFactory,
                 mTimeoutsAdapter,
                 mAsyncRingtonePlayer,
