diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 749e65e..158504b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -26,7 +26,6 @@
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
     <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/>
     <uses-permission android:name="android.permission.BLUETOOTH_MAP"/>
-    <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" />
     <uses-permission android:name="android.permission.DUMP"/>
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
@@ -425,17 +424,5 @@
             <meta-data android:name="android.accounts.AccountAuthenticator"
                  android:resource="@xml/authenticator"/>
         </service>
-        <service
-            android:name=".hfp.BluetoothInCallService"
-            android:permission="android.permission.BIND_INCALL_SERVICE"
-            android:process="@string/process"
-            android:enabled="@bool/profile_supported_hfp_incallservice"
-            android:exported="true">
-            <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
-                       android:value="true" />
-            <intent-filter>
-              <action android:name="android.telecom.InCallService"/>
-            </intent-filter>
-         </service>
     </application>
 </manifest>
diff --git a/res/values/config.xml b/res/values/config.xml
index 484253d..9a1c5b1 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -17,7 +17,6 @@
     <bool name="profile_supported_a2dp_sink">false</bool>
     <bool name="profile_supported_hs_hfp">true</bool>
     <bool name="profile_supported_hfpclient">false</bool>
-    <bool name="profile_supported_hfp_incallservice">true</bool>
     <bool name="profile_supported_hid_host">true</bool>
     <bool name="profile_supported_opp">true</bool>
     <bool name="profile_supported_pan">true</bool>
diff --git a/src/com/android/bluetooth/btservice/AdapterState.java b/src/com/android/bluetooth/btservice/AdapterState.java
index 570239b..8596627 100644
--- a/src/com/android/bluetooth/btservice/AdapterState.java
+++ b/src/com/android/bluetooth/btservice/AdapterState.java
@@ -17,13 +17,9 @@
 package com.android.bluetooth.btservice;
 
 import android.bluetooth.BluetoothAdapter;
-import android.content.ComponentName;
-import android.content.pm.PackageManager;
 import android.os.Message;
 import android.util.Log;
 
-import com.android.bluetooth.R;
-import com.android.bluetooth.hfp.BluetoothInCallService;
 import com.android.bluetooth.statemachine.State;
 import com.android.bluetooth.statemachine.StateMachine;
 
@@ -79,10 +75,6 @@
     static final int BREDR_START_TIMEOUT_DELAY = 4000;
     static final int BREDR_STOP_TIMEOUT_DELAY = 4000;
 
-    static final ComponentName BLUETOOTH_INCALLSERVICE_COMPONENT
-            = new ComponentName(R.class.getPackage().getName(),
-            BluetoothInCallService.class.getCanonicalName());
-
     private AdapterService mAdapterService;
     private TurningOnState mTurningOnState = new TurningOnState();
     private TurningBleOnState mTurningBleOnState = new TurningBleOnState();
@@ -231,24 +223,6 @@
         }
 
         @Override
-        public void enter() {
-            super.enter();
-            mAdapterService.getPackageManager().setComponentEnabledSetting(
-                    BLUETOOTH_INCALLSERVICE_COMPONENT,
-                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
-                    PackageManager.DONT_KILL_APP);
-        }
-
-        @Override
-        public void exit() {
-            mAdapterService.getPackageManager().setComponentEnabledSetting(
-                    BLUETOOTH_INCALLSERVICE_COMPONENT,
-                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                    PackageManager.DONT_KILL_APP);
-            super.exit();
-        }
-
-        @Override
         public boolean processMessage(Message msg) {
             switch (msg.what) {
                 case USER_TURN_OFF:
diff --git a/src/com/android/bluetooth/hfp/BluetoothCall.java b/src/com/android/bluetooth/hfp/BluetoothCall.java
deleted file mode 100644
index edd696e..0000000
--- a/src/com/android/bluetooth/hfp/BluetoothCall.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2020 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.bluetooth.hfp;
-
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.telecom.Call;
-import android.telecom.GatewayInfo;
-import android.telecom.InCallService;
-import android.telecom.PhoneAccountHandle;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A proxy class of android.telecom.Call that
- * 1) facilitates testing of the BluetoothInCallService class; We can't mock the final class
- * Call directly;
- * 2) Some helper functions, to let Call have same methods as com.android.server.telecom.Call
- *
- * This is necessary due to the "final" attribute of the Call class. In order to
- * test the correct functioning of the BluetoothInCallService class, the final class must be put
- * into a container that can be mocked correctly.
- */
-@VisibleForTesting
-public class BluetoothCall {
-
-    private Call mCall;
-
-    public Call getCall() {
-        return mCall;
-    }
-
-    public void setCall(Call call) {
-        mCall = call;
-    }
-
-    public BluetoothCall(Call call) {
-        mCall = call;
-    }
-
-    public String getRemainingPostDialSequence() {
-        return mCall.getRemainingPostDialSequence();
-    }
-
-    public void answer(int videoState) {
-        mCall.answer(videoState);
-    }
-
-    public void deflect(Uri address) {
-        mCall.deflect(address);
-    }
-
-    public void reject(boolean rejectWithMessage, String textMessage) {
-        mCall.reject(rejectWithMessage, textMessage);
-    }
-
-    public void disconnect() {
-        mCall.disconnect();
-    }
-
-    public void hold() {
-        mCall.hold();
-    }
-
-    public void unhold() {
-        mCall.unhold();
-    }
-
-    public void enterBackgroundAudioProcessing() {
-        mCall.enterBackgroundAudioProcessing();
-    }
-
-    public void exitBackgroundAudioProcessing(boolean shouldRing) {
-        mCall.exitBackgroundAudioProcessing(shouldRing);
-    }
-
-    public void playDtmfTone(char digit) {
-        mCall.playDtmfTone(digit);
-    }
-
-    public void stopDtmfTone() {
-        mCall.stopDtmfTone();
-    }
-
-    public void postDialContinue(boolean proceed) {
-        mCall.postDialContinue(proceed);
-    }
-
-    public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
-        mCall.phoneAccountSelected(accountHandle, setDefault);
-    }
-
-    public void conference(BluetoothCall callToConferenceWith) {
-        if (callToConferenceWith != null) {
-            mCall.conference(callToConferenceWith.getCall());
-        }
-    }
-
-    public void splitFromConference() {
-        mCall.splitFromConference();
-    }
-
-    public void mergeConference() {
-        mCall.mergeConference();
-    }
-
-    public void swapConference() {
-        mCall.swapConference();
-    }
-
-    public void pullExternalCall() {
-        mCall.pullExternalCall();
-    }
-
-    public void sendCallEvent(String event, Bundle extras) {
-        mCall.sendCallEvent(event, extras);
-    }
-
-    public void sendRttRequest() {
-        mCall.sendRttRequest();
-    }
-
-    public void respondToRttRequest(int id, boolean accept) {
-        mCall.respondToRttRequest(id, accept);
-    }
-
-    public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
-        mCall.handoverTo(toHandle, videoState, extras);
-    }
-
-    public void stopRtt() {
-        mCall.stopRtt();
-    }
-
-    public void putExtras(Bundle extras) {
-        mCall.putExtras(extras);
-    }
-
-    public void putExtra(String key, boolean value) {
-        mCall.putExtra(key, value);
-    }
-
-    public void putExtra(String key, int value) {
-        mCall.putExtra(key, value);
-    }
-
-    public void putExtra(String key, String value) {
-        mCall.putExtra(key, value);
-    }
-
-    public void removeExtras(List<String> keys) {
-        mCall.removeExtras(keys);
-    }
-
-    public void removeExtras(String... keys) {
-        mCall.removeExtras(keys);
-    }
-
-    public String getParentId() {
-        Call parent = mCall.getParent();
-        if (parent != null) {
-            return parent.getDetails().getTelecomCallId();
-        }
-        return null;
-    }
-
-    public List<String> getChildrenIds() {
-        return getIds(mCall.getChildren());
-    }
-
-    public List<String> getConferenceableCalls() {
-        return getIds(mCall.getConferenceableCalls());
-    }
-
-    public int getState() {
-        return mCall.getState();
-    }
-
-    public List<String> getCannedTextResponses() {
-        return mCall.getCannedTextResponses();
-    }
-
-    public InCallService.VideoCall getVideoCall() {
-        return mCall.getVideoCall();
-    }
-
-    public Call.Details getDetails() {
-        return mCall.getDetails();
-    }
-
-    public Call.RttCall getRttCall() {
-        return mCall.getRttCall();
-    }
-
-    public boolean isRttActive() {
-        return mCall.isRttActive();
-    }
-
-    public void registerCallback(Call.Callback callback) {
-        mCall.registerCallback(callback);
-    }
-
-    public void registerCallback(Call.Callback callback, Handler handler) {
-        mCall.registerCallback(callback, handler);
-    }
-
-    public void unregisterCallback(Call.Callback callback) {
-        mCall.unregisterCallback(callback);
-    }
-
-    public String toString() {
-        String string = mCall.toString();
-        return string == null ? "" : string;
-    }
-
-    public void addListener(Call.Listener listener) {
-        mCall.addListener(listener);
-    }
-
-    public void removeListener(Call.Listener listener) {
-        mCall.removeListener(listener);
-    }
-
-    public String getGenericConferenceActiveChildCallId() {
-        return mCall.getGenericConferenceActiveChildCall().getDetails().getTelecomCallId();
-    }
-
-    public String getContactDisplayName() {
-        return mCall.getDetails().getContactDisplayName();
-    }
-
-    public PhoneAccountHandle getAccountHandle() {
-        return mCall.getDetails().getAccountHandle();
-    }
-
-    public int getVideoState() {
-        return mCall.getDetails().getVideoState();
-    }
-
-    public String getCallerDisplayName() {
-        return mCall.getDetails().getCallerDisplayName();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o == null) {
-            return getCall() == null;
-        }
-        return o instanceof BluetoothCall && getCall() == ((BluetoothCall) o).getCall();
-    }
-
-    // helper functions
-    public boolean isSilentRingingRequested() {
-        return getDetails().getExtras().getBoolean(Call.EXTRA_SILENT_RINGING_REQUESTED);
-    }
-
-    public boolean isConference() {
-        return getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE);
-    }
-
-    public boolean can(int capability) {
-        return getDetails().can(capability);
-    }
-
-    public Uri getHandle() {
-        return getDetails().getHandle();
-    }
-
-    public GatewayInfo getGatewayInfo() {
-        return getDetails().getGatewayInfo();
-    }
-
-    public boolean isIncoming() {
-        return getDetails().getCallDirection() == Call.Details.DIRECTION_INCOMING;
-    }
-
-    public boolean isExternalCall() {
-        return getDetails().hasProperty(Call.Details.PROPERTY_IS_EXTERNAL_CALL);
-    }
-
-    public String getTelecomCallId() {
-        return getDetails().getTelecomCallId();
-    }
-
-    public boolean wasConferencePreviouslyMerged() {
-        return can(Call.Details.CAPABILITY_SWAP_CONFERENCE) &&
-                !can(Call.Details.CAPABILITY_MERGE_CONFERENCE);
-    }
-
-    public static List<String> getIds(List<Call> calls) {
-        List<String> result = new ArrayList<>();
-        for (Call call : calls) {
-            if (call != null) {
-                result.add(call.getDetails().getTelecomCallId());
-            }
-        }
-        return result;
-    }
-}
diff --git a/src/com/android/bluetooth/hfp/BluetoothHeadsetProxy.java b/src/com/android/bluetooth/hfp/BluetoothHeadsetProxy.java
deleted file mode 100644
index 824955d..0000000
--- a/src/com/android/bluetooth/hfp/BluetoothHeadsetProxy.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2020 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.bluetooth.hfp;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-
-import java.util.List;
-
-/**
- * A proxy class that facilitates testing of the BluetoothInCallService class.
- *
- * This is necessary due to the "final" attribute of the BluetoothHeadset class. In order to
- * test the correct functioning of the BluetoothInCallService class, the final class must be put
- * into a container that can be mocked correctly.
- */
-public class BluetoothHeadsetProxy {
-
-    private BluetoothHeadset mBluetoothHeadset;
-
-    public BluetoothHeadsetProxy(BluetoothHeadset headset) {
-        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();
-    }
-
-    public int getConnectionState(BluetoothDevice device) {
-        return mBluetoothHeadset.getConnectionState(device);
-    }
-
-    public int getAudioState(BluetoothDevice device) {
-        return mBluetoothHeadset.getAudioState(device);
-    }
-
-    public boolean connectAudio() {
-        return mBluetoothHeadset.connectAudio();
-    }
-
-    public boolean setActiveDevice(BluetoothDevice device) {
-        return mBluetoothHeadset.setActiveDevice(device);
-    }
-
-    public BluetoothDevice getActiveDevice() {
-        return mBluetoothHeadset.getActiveDevice();
-    }
-
-    public boolean isAudioOn() {
-        return mBluetoothHeadset.isAudioOn();
-    }
-
-    public boolean disconnectAudio() {
-        return mBluetoothHeadset.disconnectAudio();
-    }
-
-    public boolean isInbandRingingEnabled() {
-        return mBluetoothHeadset.isInbandRingingEnabled();
-    }
-}
diff --git a/src/com/android/bluetooth/hfp/BluetoothInCallService.java b/src/com/android/bluetooth/hfp/BluetoothInCallService.java
deleted file mode 100644
index 0561794..0000000
--- a/src/com/android/bluetooth/hfp/BluetoothInCallService.java
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*
- * Copyright (C) 2020 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.bluetooth.hfp;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.IBinder;
-import android.telecom.Call;
-import android.telecom.CallAudioState;
-import android.telecom.Connection;
-import android.telecom.InCallService;
-import android.telecom.PhoneAccount;
-import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
-import android.telecom.VideoProfile;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Used to receive updates about calls from the Telecom component. This service is bound to Telecom
- * while there exist calls which potentially require UI. This includes ringing (incoming), dialing
- * (outgoing), and active calls. When the last BluetoothCall is disconnected, Telecom will unbind
- * to the service triggering InCallActivity (via CallList) to finish soon after.
- */
-public class BluetoothInCallService extends InCallService {
-
-    private static final String TAG = "BluetoothInCallService";
-
-    // 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 BluetoothCall 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 BluetoothCall mOldHeldCall = null;
-    private boolean mHeadsetUpdatedRecently = false;
-    private boolean mIsDisconnectedTonePlaying = false;
-
-    private static final Object LOCK = new Object();
-    private BluetoothHeadsetProxy mBluetoothHeadset;
-
-    @VisibleForTesting
-    public TelephonyManager mTelephonyManager;
-
-    @VisibleForTesting
-    public TelecomManager mTelecomManager;
-
-    @VisibleForTesting
-    public final HashMap<String, CallStateCallback> mCallbacks = new HashMap<>();
-
-    @VisibleForTesting
-    public final HashMap<String, BluetoothCall> mBluetoothCallHashMap = new HashMap<>();
-
-    // A map from Calls to indexes used to identify calls for CLCC (C* List Current Calls).
-    private final Map<BluetoothCall, Integer> mClccIndexMap = new HashMap<>();
-
-    private static BluetoothInCallService sInstance;
-
-    public CallInfo mCallInfo = new CallInfo();
-
-    /**
-     * Listens to connections and disconnections of bluetooth headsets.  We need to save the current
-     * bluetooth headset so that we know where to send BluetoothCall updates.
-     */
-    @VisibleForTesting
-    public BluetoothProfile.ServiceListener mProfileListener =
-            new BluetoothProfile.ServiceListener() {
-                @Override
-                public void onServiceConnected(int profile, BluetoothProfile proxy) {
-                    synchronized (LOCK) {
-                        setBluetoothHeadset(new BluetoothHeadsetProxy((BluetoothHeadset) proxy));
-                        updateHeadsetWithCallState(true /* force */);
-                    }
-                }
-
-                @Override
-                public void onServiceDisconnected(int profile) {
-                    synchronized (LOCK) {
-                        setBluetoothHeadset(null);
-                    }
-                }
-            };
-
-    /**
-     * Receives events for global state changes of the bluetooth adapter.
-     */
-    // TODO: The code is moved from Telecom stack. Since we're running in the BT process itself,
-    // we may be able to simplify this in a future patch.
-    @VisibleForTesting
-    public final BroadcastReceiver mBluetoothAdapterReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            synchronized (LOCK) {
-                int state = intent
-                        .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
-                Log.d(TAG, "Bluetooth Adapter state: " + state);
-                if (state == BluetoothAdapter.STATE_ON) {
-                    queryPhoneState();
-                }
-            }
-        }
-    };
-
-    @VisibleForTesting
-    public class CallStateCallback extends Call.Callback {
-        public int mLastState;
-
-        public CallStateCallback(int initialState) {
-            mLastState = initialState;
-        }
-
-        public int getLastState() {
-            return mLastState;
-        }
-
-        public void onStateChanged(BluetoothCall call, int state) {
-            if (mCallInfo.isNullCall(call)) {
-                return;
-            }
-            if (call.isExternalCall()) {
-                return;
-            }
-
-            // If a BluetoothCall 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 BluetoothCall later transitions to DIALING/DISCONNECTED we will then
-            // send out the aggregated update.
-            if (getLastState() == Call.STATE_ACTIVE && state == Call.STATE_HOLDING) {
-                for (BluetoothCall otherCall : mCallInfo.getBluetoothCalls()) {
-                    if (otherCall.getState() == Call.STATE_CONNECTING) {
-                        mLastState = state;
-                        return;
-                    }
-                }
-            }
-
-            // To have an active BluetoothCall and another dialing at the same time is an invalid BT
-            // state. We can assume that the active BluetoothCall will be automatically held
-            // which will send another update at which point we will be in the right state.
-            BluetoothCall activeCall = mCallInfo.getActiveCall();
-            if (!mCallInfo.isNullCall(activeCall)
-                    && getLastState() == Call.STATE_CONNECTING
-                    && (state == Call.STATE_DIALING || state == Call.STATE_PULLING_CALL)) {
-                mLastState = state;
-                return;
-            }
-            mLastState = state;
-            updateHeadsetWithCallState(false /* force */);
-        }
-
-        @Override
-        public void onStateChanged(Call call, int state) {
-            super.onStateChanged(call, state);
-            onStateChanged(getBluetoothCallById(call.getDetails().getTelecomCallId()), state);
-        }
-
-        public void onDetailsChanged(BluetoothCall call, Call.Details details) {
-            if (mCallInfo.isNullCall(call)) {
-                return;
-            }
-            if (call.isExternalCall()) {
-                onCallRemoved(call);
-            } else {
-                onCallAdded(call);
-            }
-        }
-
-        @Override
-        public void onDetailsChanged(Call call, Call.Details details) {
-            super.onDetailsChanged(call, details);
-            onDetailsChanged(getBluetoothCallById(call.getDetails().getTelecomCallId()), details);
-        }
-
-        public void onParentChanged(BluetoothCall call, BluetoothCall parent) {
-            if (call.isExternalCall()) {
-                return;
-            }
-            if (call.getParentId() != null) {
-                // If this BluetoothCall is newly conferenced, ignore the callback.
-                // We only care about the one sent for the parent conference call.
-                Log.d(TAG,
-                        "Ignoring onIsConferenceChanged from child BluetoothCall with new parent");
-                return;
-            }
-            updateHeadsetWithCallState(false /* force */);
-        }
-
-        @Override
-        public void onParentChanged(Call call, Call parent) {
-            super.onParentChanged(call, parent);
-            onParentChanged(
-                    getBluetoothCallById(call.getDetails().getTelecomCallId()),
-                    getBluetoothCallById(parent.getDetails().getTelecomCallId()));
-        }
-
-        public void onChildrenChanged(BluetoothCall call, List<BluetoothCall> children) {
-            if (call.isExternalCall()) {
-                return;
-            }
-            if (call.getChildrenIds().size() == 1) {
-                // If this is a parent BluetoothCall with only one child,
-                // ignore the callback as well since the minimum number of child calls to
-                // start a conference BluetoothCall is 2. We expect this to be called again
-                // when the parent BluetoothCall has another child BluetoothCall added.
-                Log.d(TAG,
-                        "Ignoring onIsConferenceChanged from parent with only one child call");
-                return;
-            }
-            updateHeadsetWithCallState(false /* force */);
-        }
-
-        @Override
-        public void onChildrenChanged(Call call, List<Call> children) {
-            super.onChildrenChanged(call, children);
-            onChildrenChanged(
-                    getBluetoothCallById(call.getDetails().getTelecomCallId()),
-                    getBluetoothCallsByIds(BluetoothCall.getIds(children)));
-        }
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        Log.i(TAG, "onBind. Intent: " + intent);
-        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
-            Log.i(TAG, "Bluetooth is off");
-            ComponentName componentName
-                    = new ComponentName(getPackageName(), this.getClass().getName());
-            getPackageManager().setComponentEnabledSetting(
-                    componentName,
-                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                    PackageManager.DONT_KILL_APP);
-            return null;
-        }
-        IBinder binder = super.onBind(intent);
-        IntentFilter intentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
-        registerReceiver(mBluetoothAdapterReceiver, intentFilter);
-        mTelephonyManager = getSystemService(TelephonyManager.class);
-        mTelecomManager = getSystemService(TelecomManager.class);
-        return binder;
-    }
-
-    @Override
-    public boolean onUnbind(Intent intent) {
-        Log.i(TAG, "onUnbind. Intent: " + intent);
-        unregisterReceiver(mBluetoothAdapterReceiver);
-        return super.onUnbind(intent);
-    }
-
-    public BluetoothInCallService() {
-        Log.i(TAG, "onCreate");
-        BluetoothAdapter.getDefaultAdapter()
-                .getProfileProxy(this, mProfileListener, BluetoothProfile.HEADSET);
-        sInstance = this;
-    }
-
-    public static BluetoothInCallService getInstance() {
-        return sInstance;
-    }
-
-    protected void enforceModifyPermission() {
-        enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
-    }
-
-    public boolean answerCall() {
-        synchronized (LOCK) {
-            enforceModifyPermission();
-            Log.i(TAG, "BT - answering call");
-            BluetoothCall call = mCallInfo.getRingingOrSimulatedRingingCall();
-            if (mCallInfo.isNullCall(call)) {
-                return false;
-            }
-            call.answer(VideoProfile.STATE_AUDIO_ONLY);
-            return true;
-        }
-    }
-
-    public boolean hangupCall() {
-        synchronized (LOCK) {
-            enforceModifyPermission();
-            Log.i(TAG, "BT - hanging up call");
-            BluetoothCall call = mCallInfo.getForegroundCall();
-            if (mCallInfo.isNullCall(call)) {
-                return false;
-            }
-            call.disconnect();
-            return true;
-        }
-    }
-
-    public boolean sendDtmf(int dtmf) {
-        synchronized (LOCK) {
-            enforceModifyPermission();
-            Log.i(TAG, "BT - sendDtmf " + dtmf);
-            BluetoothCall call = mCallInfo.getForegroundCall();
-            if (mCallInfo.isNullCall(call)) {
-                return false;
-            }
-            // TODO: Consider making this a queue instead of starting/stopping
-            // in quick succession.
-            call.playDtmfTone((char) dtmf);
-            call.stopDtmfTone();
-            return true;
-        }
-    }
-
-    public String getNetworkOperator()  {
-        synchronized (LOCK) {
-            enforceModifyPermission();
-            Log.i(TAG, "getNetworkOperator");
-            PhoneAccount account = mCallInfo.getBestPhoneAccount();
-            if (account != null && account.getLabel() != null) {
-                return account.getLabel().toString();
-            }
-            // Finally, just get the network name from telephony.
-            return mTelephonyManager.getNetworkOperatorName();
-        }
-    }
-
-    public String getSubscriberNumber() {
-        synchronized (LOCK) {
-            enforceModifyPermission();
-            Log.i(TAG, "getSubscriberNumber");
-            String address = null;
-            PhoneAccount account = mCallInfo.getBestPhoneAccount();
-            if (account != null) {
-                Uri addressUri = account.getAddress();
-                if (addressUri != null) {
-                    address = addressUri.getSchemeSpecificPart();
-                }
-            }
-            if (TextUtils.isEmpty(address)) {
-                address = mTelephonyManager.getLine1Number();
-                if (address == null) address = "";
-            }
-            return address;
-        }
-    }
-
-    public boolean listCurrentCalls() {
-        synchronized (LOCK) {
-            enforceModifyPermission();
-            // 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;
-        }
-    }
-
-    public boolean queryPhoneState() {
-        synchronized (LOCK) {
-            enforceModifyPermission();
-            Log.i(TAG, "queryPhoneState");
-            updateHeadsetWithCallState(true);
-            return true;
-        }
-    }
-
-    public boolean processChld(int chld) {
-        synchronized (LOCK) {
-            enforceModifyPermission();
-            long token = Binder.clearCallingIdentity();
-            Log.i(TAG, "processChld " + chld);
-            return _processChld(chld);
-        }
-    }
-
-    public void onCallAdded(BluetoothCall call) {
-        if (call.isExternalCall()) {
-            return;
-        }
-        if (!mBluetoothCallHashMap.containsKey(call.getTelecomCallId())) {
-            Log.d(TAG, "onCallAdded");
-            CallStateCallback callback = new CallStateCallback(call.getState());
-            mCallbacks.put(call.getTelecomCallId(), callback);
-            call.registerCallback(callback);
-
-            mBluetoothCallHashMap.put(call.getTelecomCallId(), call);
-            updateHeadsetWithCallState(false /* force */);
-        }
-    }
-
-    @Override
-    public void onCallAdded(Call call) {
-        super.onCallAdded(call);
-        onCallAdded(new BluetoothCall(call));
-    }
-
-    public void onCallRemoved(BluetoothCall call) {
-        if (call.isExternalCall()) {
-            return;
-        }
-        Log.d(TAG, "onCallRemoved");
-        CallStateCallback callback = getCallback(call);
-        if (callback != null) {
-            call.unregisterCallback(callback);
-        }
-
-        if (mBluetoothCallHashMap.containsKey(call.getTelecomCallId())) {
-            mBluetoothCallHashMap.remove(call.getTelecomCallId());
-        }
-
-        mClccIndexMap.remove(call);
-        updateHeadsetWithCallState(false /* force */);
-    }
-
-    @Override
-    public void onCallRemoved(Call call) {
-        super.onCallRemoved(call);
-        onCallRemoved(getBluetoothCallById(call.getDetails().getTelecomCallId()));
-    }
-
-    @Override
-    public void onCallAudioStateChanged(CallAudioState audioState) {
-        super.onCallAudioStateChanged(audioState);
-        Log.d(TAG, "onCallAudioStateChanged, audioState == " + audioState);
-    }
-
-
-    @Override
-    public void onCreate() {
-        Log.d(TAG, "onCreate");
-        super.onCreate();
-    }
-
-    @Override
-    public void onDestroy() {
-        Log.d(TAG, "onDestroy");
-        super.onDestroy();
-    }
-
-    private void sendListOfCalls(boolean shouldLog) {
-        Collection<BluetoothCall> calls = mCallInfo.getBluetoothCalls();
-        for (BluetoothCall call : calls) {
-            // We don't send the parent conference BluetoothCall 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();
-    }
-
-    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);
-        }
-    }
-
-    /**
-     * Sends a single clcc (C* List Current Calls) event for the specified call.
-     */
-    private void sendClccForCall(BluetoothCall call, boolean shouldLog) {
-        boolean isForeground = mCallInfo.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;
-        }
-
-        BluetoothCall conferenceCall = getBluetoothCallById(call.getParentId());
-        if (!mCallInfo.isNullCall(conferenceCall)) {
-            isPartOfConference = true;
-
-            // Run some alternative states for Conference-level merge/swap support.
-            // Basically, if BluetoothCall 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 BluetoothCall and that the conference itself has a notion of
-            // the current "active" child call.
-            BluetoothCall activeChild = getBluetoothCallById(
-                    conferenceCall.getGenericConferenceActiveChildCallId());
-            if (state == CALL_STATE_ACTIVE && !mCallInfo.isNullCall(activeChild)) {
-                // 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() == Call.STATE_HOLDING
-                    && conferenceCall.can(Connection.CAPABILITY_MANAGE_CONFERENCE)) {
-                // If the parent IMS CEP conference BluetoothCall is on hold, we should mark
-                // this BluetoothCall 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 BluetoothCall without conference
-            // event package support.
-            // The BluetoothCall 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(TAG, "sending clcc for BluetoothCall "
-                            + index + ", "
-                            + direction + ", "
-                            + state + ", "
-                            + isPartOfConference + ", "
-                            + addressType);
-        }
-
-        if (mBluetoothHeadset != null) {
-            mBluetoothHeadset.clccResponse(
-                    index, direction, state, 0, isPartOfConference, address, addressType);
-        }
-    }
-
-    /**
-     * 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(BluetoothCall 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;
-    }
-
-    private boolean _processChld(int chld) {
-        BluetoothCall activeCall = mCallInfo.getActiveCall();
-        BluetoothCall ringingCall = mCallInfo.getRingingOrSimulatedRingingCall();
-        if (ringingCall == null) {
-            Log.i(TAG, "asdf ringingCall null");
-        } else {
-            Log.i(TAG, "asdf ringingCall not null " + ringingCall.hashCode());
-        }
-
-        BluetoothCall heldCall = mCallInfo.getHeldCall();
-
-        Log.i(TAG, "Active: " + activeCall
-                + " Ringing: " + ringingCall
-                + " Held: " + heldCall);
-        Log.i(TAG, "asdf chld " + chld);
-
-        if (chld == CHLD_TYPE_RELEASEHELD) {
-            Log.i(TAG, "asdf CHLD_TYPE_RELEASEHELD");
-            if (!mCallInfo.isNullCall(ringingCall)) {
-                Log.i(TAG, "asdf reject " + ringingCall.hashCode());
-                ringingCall.reject(false, null);
-                return true;
-            } else if (!mCallInfo.isNullCall(heldCall)) {
-                heldCall.disconnect();
-                return true;
-            }
-        } else if (chld == CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD) {
-            if (mCallInfo.isNullCall(activeCall)
-                    && mCallInfo.isNullCall(ringingCall)
-                    && mCallInfo.isNullCall(heldCall)) {
-                return false;
-            }
-            if (!mCallInfo.isNullCall(activeCall)) {
-                activeCall.disconnect();
-                if (!mCallInfo.isNullCall(ringingCall)) {
-                    ringingCall.answer(VideoProfile.STATE_AUDIO_ONLY);
-                }
-                return true;
-            }
-            if (!mCallInfo.isNullCall(ringingCall)) {
-                ringingCall.answer(ringingCall.getVideoState());
-            } else if (!mCallInfo.isNullCall(heldCall)) {
-                heldCall.unhold();
-            }
-            return true;
-        } else if (chld == CHLD_TYPE_HOLDACTIVE_ACCEPTHELD) {
-            if (!mCallInfo.isNullCall(activeCall)
-                    && 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 (!mCallInfo.isNullCall(ringingCall)) {
-                ringingCall.answer(VideoProfile.STATE_AUDIO_ONLY);
-                return true;
-            } else if (!mCallInfo.isNullCall(heldCall)) {
-                // CallsManager will hold any active calls when unhold() is called on a
-                // currently-held call.
-                heldCall.unhold();
-                return true;
-            } else if (!mCallInfo.isNullCall(activeCall)
-                    && activeCall.can(Connection.CAPABILITY_HOLD)) {
-                activeCall.hold();
-                return true;
-            }
-        } else if (chld == CHLD_TYPE_ADDHELDTOCONF) {
-            if (!mCallInfo.isNullCall(activeCall)) {
-                if (activeCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)) {
-                    activeCall.mergeConference();
-                    return true;
-                } else {
-                    List<BluetoothCall> conferenceable = getBluetoothCallsByIds(
-                            activeCall.getConferenceableCalls());
-                    if (!conferenceable.isEmpty()) {
-                        activeCall.conference(conferenceable.get(0));
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Sends an update of the current BluetoothCall 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) {
-        BluetoothCall activeCall = mCallInfo.getActiveCall();
-        BluetoothCall ringingCall = mCallInfo.getRingingOrSimulatedRingingCall();
-        BluetoothCall heldCall = mCallInfo.getHeldCall();
-
-        int bluetoothCallState = getBluetoothCallStateForUpdate();
-
-        String ringingAddress = null;
-        int ringingAddressType = DEFAULT_RINGING_ADDRESS_TYPE;
-        String ringingName = null;
-        if (!mCallInfo.isNullCall(ringingCall) && 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.getContactDisplayName();
-            }
-        }
-        if (ringingAddress == null) {
-            ringingAddress = "";
-        }
-
-        int numActiveCalls = mCallInfo.isNullCall(activeCall) ? 0 : 1;
-        int numHeldCalls = mCallInfo.getNumHeldCalls();
-        int numChildrenOfActiveCall =
-                mCallInfo.isNullCall(activeCall) ? 0 : activeCall.getChildrenIds().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 BluetoothCall within the
-        // conference (namely CDMA calls) we need to expose that as a held BluetoothCall
-        // in order for the BT device to show "swap" and "merge" functionality.
-        boolean ignoreHeldCallChange = false;
-        if (!mCallInfo.isNullCall(activeCall) && 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
-                // BluetoothCall 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 (String id : activeCall.getChildrenIds()) {
-                // Held BluetoothCall 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 BluetoothCall change.
-                if (mOldHeldCall != null && mOldHeldCall.getTelecomCallId() == id) {
-                    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 BluetoothCall 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 " + mNumActiveCalls + ", "
-                                + "numHeld " + mNumHeldCalls + ", "
-                                + "callState " + CALL_STATE_DIALING + ", "
-                                + "ringing type " + mRingingAddressType);
-                mBluetoothHeadset.phoneStateChanged(
-                        mNumActiveCalls,
-                        mNumHeldCalls,
-                        CALL_STATE_DIALING,
-                        mRingingAddress,
-                        mRingingAddressType,
-                        ringingName);
-            }
-
-            Log.i(TAG, "updateHeadsetWithCallState "
-                    + "numActive " + mNumActiveCalls + ", "
-                    + "numHeld " + mNumHeldCalls + ", "
-                    + "callState " + mBluetoothCallState + ", "
-                    + "ringing type " + mRingingAddressType);
-
-            mBluetoothHeadset.phoneStateChanged(
-                    mNumActiveCalls,
-                    mNumHeldCalls,
-                    mBluetoothCallState,
-                    mRingingAddress,
-                    mRingingAddressType,
-                    ringingName);
-
-            mHeadsetUpdatedRecently = true;
-        }
-    }
-
-    private int getBluetoothCallStateForUpdate() {
-        BluetoothCall ringingCall = mCallInfo.getRingingOrSimulatedRingingCall();
-        BluetoothCall dialingCall = mCallInfo.getOutgoingCall();
-        boolean hasOnlyDisconnectedCalls = mCallInfo.hasOnlyDisconnectedCalls();
-
-        //
-        // !! WARNING !!
-        // You will note that CALL_STATE_WAITING, CALL_STATE_HELD, and CALL_STATE_ACTIVE are not
-        // used in this version of the BluetoothCall 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 (!mCallInfo.isNullCall(ringingCall) && !ringingCall.isSilentRingingRequested()) {
-            bluetoothCallState = CALL_STATE_INCOMING;
-        } else if (!mCallInfo.isNullCall(dialingCall)) {
-            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(BluetoothCall call, boolean isForeground) {
-        switch (call.getState()) {
-            case Call.STATE_NEW:
-            case Call.STATE_DISCONNECTED:
-            case Call.STATE_AUDIO_PROCESSING:
-                return CALL_STATE_IDLE;
-
-            case Call.STATE_ACTIVE:
-                return CALL_STATE_ACTIVE;
-
-            case Call.STATE_CONNECTING:
-            case Call.STATE_SELECT_PHONE_ACCOUNT:
-            case Call.STATE_DIALING:
-            case Call.STATE_PULLING_CALL:
-                // Yes, this is correctly returning ALERTING.
-                // "Dialing" for BT means that we have sent information to the service provider
-                // to place the BluetoothCall but there is no confirmation that the BluetoothCall
-                // 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 Call.STATE_HOLDING:
-                return CALL_STATE_HELD;
-
-            case Call.STATE_RINGING:
-            case Call.STATE_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;
-    }
-
-    @VisibleForTesting
-    public CallStateCallback getCallback(BluetoothCall call) {
-        return mCallbacks.get(call.getTelecomCallId());
-    }
-
-    @VisibleForTesting
-    public void setBluetoothHeadset(BluetoothHeadsetProxy bluetoothHeadset) {
-        mBluetoothHeadset = bluetoothHeadset;
-    }
-
-    @VisibleForTesting
-    public BluetoothCall getBluetoothCallById(String id) {
-        if (mBluetoothCallHashMap.containsKey(id)) {
-            return mBluetoothCallHashMap.get(id);
-        }
-        return null;
-    }
-
-    @VisibleForTesting
-    public List<BluetoothCall> getBluetoothCallsByIds(List<String> ids) {
-        List<BluetoothCall> calls = new ArrayList<>();
-        for (String id : ids) {
-            BluetoothCall call = getBluetoothCallById(id);
-            if (!mCallInfo.isNullCall(call)) {
-                calls.add(call);
-            }
-        }
-        return calls;
-    }
-
-    // extract call information functions out into this part, so we can mock it in testing
-    @VisibleForTesting
-    public class CallInfo {
-
-        public BluetoothCall getForegroundCall() {
-            LinkedHashSet<Integer> states = new LinkedHashSet<Integer>();
-            BluetoothCall foregroundCall;
-
-            states.add(Call.STATE_CONNECTING);
-            foregroundCall = getCallByStates(states);
-            if (!mCallInfo.isNullCall(foregroundCall)) {
-                return foregroundCall;
-            }
-
-            states.clear();
-            states.add(Call.STATE_ACTIVE);
-            states.add(Call.STATE_DIALING);
-            states.add(Call.STATE_PULLING_CALL);
-            foregroundCall = getCallByStates(states);
-            if (!mCallInfo.isNullCall(foregroundCall)) {
-                return foregroundCall;
-            }
-
-            states.clear();
-            states.add(Call.STATE_RINGING);
-            foregroundCall = getCallByStates(states);
-            if (!mCallInfo.isNullCall(foregroundCall)) {
-                return foregroundCall;
-            }
-
-            return null;
-        }
-
-        public BluetoothCall getCallByStates(LinkedHashSet<Integer> states) {
-            List<BluetoothCall> calls = getBluetoothCalls();
-            for (BluetoothCall call : calls) {
-                if (states.contains(call.getState())) {
-                    return call;
-                }
-            }
-            return null;
-        }
-
-        public BluetoothCall getCallByState(int state) {
-            List<BluetoothCall> calls = getBluetoothCalls();
-            for (BluetoothCall call : calls) {
-                if (state == call.getState()) {
-                    return call;
-                }
-            }
-            return null;
-        }
-
-        public int getNumHeldCalls() {
-            int number = 0;
-            List<BluetoothCall> calls = getBluetoothCalls();
-            for (BluetoothCall call : calls) {
-                if (call.getState() == Call.STATE_HOLDING) {
-                    number++;
-                }
-            }
-            return number;
-        }
-
-        public boolean hasOnlyDisconnectedCalls() {
-            List<BluetoothCall> calls = getBluetoothCalls();
-            if (calls.size() == 0) {
-                return false;
-            }
-            for (BluetoothCall call : calls) {
-                if (call.getState() != Call.STATE_DISCONNECTED) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        public List<BluetoothCall> getBluetoothCalls() {
-            return getBluetoothCallsByIds(BluetoothCall.getIds(getCalls()));
-        }
-
-        public BluetoothCall getOutgoingCall() {
-            LinkedHashSet<Integer> states = new LinkedHashSet<Integer>();
-            states.add(Call.STATE_CONNECTING);
-            states.add(Call.STATE_DIALING);
-            states.add(Call.STATE_PULLING_CALL);
-            return getCallByStates(states);
-        }
-
-        public BluetoothCall getRingingOrSimulatedRingingCall() {
-            LinkedHashSet<Integer> states = new LinkedHashSet<Integer>();
-            states.add(Call.STATE_RINGING);
-            states.add(Call.STATE_SIMULATED_RINGING);
-            return getCallByStates(states);
-        }
-
-        public BluetoothCall getActiveCall() {
-            return getCallByState(Call.STATE_ACTIVE);
-        }
-
-        public BluetoothCall getHeldCall() {
-            return getCallByState(Call.STATE_HOLDING);
-        }
-
-        /**
-         * 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.
-         */
-        public PhoneAccount getBestPhoneAccount() {
-            BluetoothCall call = getForegroundCall();
-
-            PhoneAccount account = null;
-            if (!mCallInfo.isNullCall(call)) {
-                PhoneAccountHandle handle = call.getAccountHandle();
-                if (handle != null) {
-                    // First try to get the network name of the foreground call.
-                    account = mTelecomManager.getPhoneAccount(handle);
-                }
-            }
-
-            if (account == null) {
-                // Second, Try to get the label for the default Phone Account.
-                List<PhoneAccountHandle> handles =
-                        mTelecomManager.getPhoneAccountsSupportingScheme(PhoneAccount.SCHEME_TEL);
-                while (handles.iterator().hasNext()) {
-                    account = mTelecomManager.getPhoneAccount(handles.iterator().next());
-                    if (account != null) {
-                        return account;
-                    }
-                }
-            }
-            return null;
-        }
-
-        public boolean isNullCall(BluetoothCall call) {
-            return call == null || call.getCall() == null;
-        }
-    };
-};
diff --git a/src/com/android/bluetooth/hfp/HeadsetService.java b/src/com/android/bluetooth/hfp/HeadsetService.java
index 7c08f15..6031a93 100644
--- a/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -153,6 +153,7 @@
         mStateMachinesThread.start();
         // Step 3: Initialize system interface
         mSystemInterface = HeadsetObjectsFactory.getInstance().makeSystemInterface(this);
+        mSystemInterface.init();
         // Step 4: Initialize native interface
         mMaxHeadsetConnections = mAdapterService.getMaxConnectedAudioDevices();
         mNativeInterface = HeadsetObjectsFactory.getInstance().getNativeInterface();
diff --git a/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java b/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java
index a618019..52ca1bc 100644
--- a/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java
+++ b/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java
@@ -20,15 +20,19 @@
 import android.annotation.Nullable;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.IBluetoothHeadsetPhone;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.media.AudioManager;
+import android.os.IBinder;
 import android.os.PowerManager;
+import android.os.RemoteException;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -48,6 +52,28 @@
     private final AudioManager mAudioManager;
     private final HeadsetPhoneState mHeadsetPhoneState;
     private PowerManager.WakeLock mVoiceRecognitionWakeLock;
+    private volatile IBluetoothHeadsetPhone mPhoneProxy;
+    private final ServiceConnection mPhoneProxyConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) {
+                Log.d(TAG, "Proxy object connected");
+            }
+            synchronized (HeadsetSystemInterface.this) {
+                mPhoneProxy = IBluetoothHeadsetPhone.Stub.asInterface(service);
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) {
+                Log.d(TAG, "Proxy object disconnected");
+            }
+            synchronized (HeadsetSystemInterface.this) {
+                mPhoneProxy = null;
+            }
+        }
+    };
 
     HeadsetSystemInterface(HeadsetService headsetService) {
         if (headsetService == null) {
@@ -60,11 +86,21 @@
         mVoiceRecognitionWakeLock =
                 powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG + ":VoiceRecognition");
         mVoiceRecognitionWakeLock.setReferenceCounted(false);
-        mHeadsetPhoneState = new com.android.bluetooth.hfp.HeadsetPhoneState(mHeadsetService);
+        mHeadsetPhoneState = new HeadsetPhoneState(mHeadsetService);
     }
 
-    private BluetoothInCallService getBluetoothInCallServiceInstance() {
-        return BluetoothInCallService.getInstance();
+    /**
+     * Initialize this system interface
+     */
+    public synchronized void init() {
+        // Bind to Telecom phone proxy service
+        Intent intent = new Intent(IBluetoothHeadsetPhone.class.getName());
+        intent.setComponent(resolveSystemService(mHeadsetService.getPackageManager(), 0, intent));
+        if (intent.getComponent() == null || !mHeadsetService.bindService(intent,
+                mPhoneProxyConnection, 0)) {
+            // Crash the stack if cannot bind to Telecom
+            Log.wtf(TAG, "Could not bind to IBluetoothHeadsetPhone Service, intent=" + intent);
+        }
     }
 
     /**
@@ -104,6 +140,14 @@
      * Stop this system interface
      */
     public synchronized void stop() {
+        if (mPhoneProxy != null) {
+            if (DBG) {
+                Log.d(TAG, "Unbinding phone proxy");
+            }
+            mPhoneProxy = null;
+            // Synchronization should make sure unbind can be successful
+            mHeadsetService.unbindService(mPhoneProxyConnection);
+        }
         mHeadsetPhoneState.cleanup();
     }
 
@@ -149,10 +193,14 @@
             Log.w(TAG, "answerCall device is null");
             return;
         }
-        BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance();
-        if (bluetoothInCallService != null) {
-            mHeadsetService.setActiveDevice(device);
-            bluetoothInCallService.answerCall();
+
+        if (mPhoneProxy != null) {
+            try {
+                mHeadsetService.setActiveDevice(device);
+                mPhoneProxy.answerCall();
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+            }
         } else {
             Log.e(TAG, "Handsfree phone proxy null for answering call");
         }
@@ -174,9 +222,12 @@
         if (mHeadsetService.isVirtualCallStarted()) {
             mHeadsetService.stopScoUsingVirtualVoiceCall();
         } else {
-            BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance();
-            if (bluetoothInCallService != null) {
-                bluetoothInCallService.hangupCall();
+            if (mPhoneProxy != null) {
+                try {
+                    mPhoneProxy.hangupCall();
+                } catch (RemoteException e) {
+                    Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                }
             } else {
                 Log.e(TAG, "Handsfree phone proxy null for hanging up call");
             }
@@ -195,9 +246,12 @@
             Log.w(TAG, "sendDtmf device is null");
             return false;
         }
-        BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance();
-        if (bluetoothInCallService != null) {
-            return bluetoothInCallService.sendDtmf(dtmf);
+        if (mPhoneProxy != null) {
+            try {
+                return mPhoneProxy.sendDtmf(dtmf);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+            }
         } else {
             Log.e(TAG, "Handsfree phone proxy null for sending DTMF");
         }
@@ -211,9 +265,12 @@
      */
     @VisibleForTesting
     public boolean processChld(int chld) {
-        BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance();
-        if (bluetoothInCallService != null) {
-            return bluetoothInCallService.processChld(chld);
+        if (mPhoneProxy != null) {
+            try {
+                return mPhoneProxy.processChld(chld);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+            }
         } else {
             Log.e(TAG, "Handsfree phone proxy null for sending DTMF");
         }
@@ -227,13 +284,19 @@
      */
     @VisibleForTesting
     public String getNetworkOperator() {
-        BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance();
-        if (bluetoothInCallService == null) {
-            Log.e(TAG, "getNetworkOperator() failed: mBluetoothInCallService is null");
+        final IBluetoothHeadsetPhone phoneProxy = mPhoneProxy;
+        if (phoneProxy == null) {
+            Log.e(TAG, "getNetworkOperator() failed: mPhoneProxy is null");
             return null;
         }
-        // Should never return null
-        return bluetoothInCallService.getNetworkOperator();
+        try {
+            // Should never return null
+            return mPhoneProxy.getNetworkOperator();
+        } catch (RemoteException exception) {
+            Log.e(TAG, "getNetworkOperator() failed: " + exception.getMessage());
+            exception.printStackTrace();
+            return null;
+        }
     }
 
     /**
@@ -243,12 +306,18 @@
      */
     @VisibleForTesting
     public String getSubscriberNumber() {
-        BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance();
-        if (bluetoothInCallService == null) {
-            Log.e(TAG, "getSubscriberNumber() failed: mBluetoothInCallService is null");
+        final IBluetoothHeadsetPhone phoneProxy = mPhoneProxy;
+        if (phoneProxy == null) {
+            Log.e(TAG, "getSubscriberNumber() failed: mPhoneProxy is null");
             return null;
         }
-        return bluetoothInCallService.getSubscriberNumber();
+        try {
+            return mPhoneProxy.getSubscriberNumber();
+        } catch (RemoteException exception) {
+            Log.e(TAG, "getSubscriberNumber() failed: " + exception.getMessage());
+            exception.printStackTrace();
+            return null;
+        }
     }
 
 
@@ -260,12 +329,18 @@
      */
     @VisibleForTesting
     public boolean listCurrentCalls() {
-        BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance();
-        if (bluetoothInCallService == null) {
-            Log.e(TAG, "listCurrentCalls() failed: mBluetoothInCallService is null");
+        final IBluetoothHeadsetPhone phoneProxy = mPhoneProxy;
+        if (phoneProxy == null) {
+            Log.e(TAG, "listCurrentCalls() failed: mPhoneProxy is null");
             return false;
         }
-        return bluetoothInCallService.listCurrentCalls();
+        try {
+            return mPhoneProxy.listCurrentCalls();
+        } catch (RemoteException exception) {
+            Log.e(TAG, "listCurrentCalls() failed: " + exception.getMessage());
+            exception.printStackTrace();
+            return false;
+        }
     }
 
     /**
@@ -274,9 +349,13 @@
      */
     @VisibleForTesting
     public void queryPhoneState() {
-        BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance();
-        if (bluetoothInCallService != null) {
-            bluetoothInCallService.queryPhoneState();
+        final IBluetoothHeadsetPhone phoneProxy = mPhoneProxy;
+        if (phoneProxy != null) {
+            try {
+                mPhoneProxy.queryPhoneState();
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+            }
         } else {
             Log.e(TAG, "Handsfree phone proxy null for query phone state");
         }
diff --git a/tests/unit/src/com/android/bluetooth/hfp/BluetoothInCallServiceTest.java b/tests/unit/src/com/android/bluetooth/hfp/BluetoothInCallServiceTest.java
deleted file mode 100644
index 8f9f544..0000000
--- a/tests/unit/src/com/android/bluetooth/hfp/BluetoothInCallServiceTest.java
+++ /dev/null
@@ -1,1186 +0,0 @@
-/*
- * Copyright (C) 2020 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.bluetooth.hfp;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.*;
-
-import android.bluetooth.BluetoothAdapter;
-import android.content.ComponentName;
-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.telecom.Call;
-import android.telecom.Connection;
-import android.telecom.GatewayInfo;
-import android.telecom.PhoneAccount;
-import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.rule.ServiceTestRule;
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Tests for {@link BluetoothInCallService}
- */
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class BluetoothInCallServiceTest {
-
-    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;
-
-    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 TestableBluetoothInCallService mBluetoothInCallService;
-    @Rule public final ServiceTestRule mServiceRule
-            = ServiceTestRule.withTimeout(1, TimeUnit.SECONDS);
-
-    @Mock private BluetoothHeadsetProxy mMockBluetoothHeadset;
-    @Mock private BluetoothInCallService.CallInfo mMockCallInfo;
-    @Mock private TelephonyManager mMockTelephonyManager;
-
-    public class TestableBluetoothInCallService extends BluetoothInCallService {
-        @Override
-        public IBinder onBind(Intent intent) {
-            IBinder binder = super.onBind(intent);
-            IntentFilter intentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
-            registerReceiver(mBluetoothAdapterReceiver, intentFilter);
-            mTelephonyManager = getSystemService(TelephonyManager.class);
-            mTelecomManager = getSystemService(TelecomManager.class);
-            return binder;
-        }
-        @Override
-        protected void enforceModifyPermission() {}
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        // Create the service Intent.
-        Intent serviceIntent =
-                new Intent(ApplicationProvider.getApplicationContext(),
-                        TestableBluetoothInCallService.class);
-        // Bind the service
-        mServiceRule.bindService(serviceIntent);
-
-        // 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.
-        doReturn(null).when(mMockCallInfo).getActiveCall();
-        doReturn(null).when(mMockCallInfo)
-                .getRingingOrSimulatedRingingCall();
-        doReturn(null).when(mMockCallInfo).getHeldCall();
-        doReturn(null).when(mMockCallInfo).getOutgoingCall();
-        doReturn(0).when(mMockCallInfo).getNumHeldCalls();
-        doReturn(false).when(mMockCallInfo).hasOnlyDisconnectedCalls();
-        doReturn(true).when(mMockCallInfo).isNullCall(null);
-        doReturn(false).when(mMockCallInfo).isNullCall(notNull());
-
-        mBluetoothInCallService = new TestableBluetoothInCallService();
-        mBluetoothInCallService.setBluetoothHeadset(mMockBluetoothHeadset);
-        mBluetoothInCallService.mCallInfo = mMockCallInfo;
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mServiceRule.unbindService();
-        mBluetoothInCallService = null;
-    }
-
-    @Test
-    public void testHeadsetAnswerCall() throws Exception {
-        BluetoothCall mockCall = createRingingCall();
-
-        boolean callAnswered = mBluetoothInCallService.answerCall();
-        verify(mockCall).answer(any(int.class));
-
-        Assert.assertTrue(callAnswered);
-    }
-
-    @Test
-    public void testHeadsetAnswerCallNull() throws Exception {
-        when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(null);
-
-        boolean callAnswered = mBluetoothInCallService.answerCall();
-        Assert.assertFalse(callAnswered);
-    }
-
-    @Test
-    public void testHeadsetHangupCall() throws Exception {
-        BluetoothCall mockCall = createForegroundCall();
-
-        boolean callHungup = mBluetoothInCallService.hangupCall();
-
-        verify(mockCall).disconnect();
-        Assert.assertTrue(callHungup);
-    }
-
-    @Test
-    public void testHeadsetHangupCallNull() throws Exception {
-        when(mMockCallInfo.getForegroundCall()).thenReturn(null);
-
-        boolean callHungup = mBluetoothInCallService.hangupCall();
-        Assert.assertFalse(callHungup);
-    }
-
-    @Test
-    public void testHeadsetSendDTMF() throws Exception {
-        BluetoothCall mockCall = createForegroundCall();
-
-        boolean sentDtmf = mBluetoothInCallService.sendDtmf(TEST_DTMF_TONE);
-
-        verify(mockCall).playDtmfTone(eq((char) TEST_DTMF_TONE));
-        verify(mockCall).stopDtmfTone();
-        Assert.assertTrue(sentDtmf);
-    }
-
-    @Test
-    public void testHeadsetSendDTMFNull() throws Exception {
-        when(mMockCallInfo.getForegroundCall()).thenReturn(null);
-
-        boolean sentDtmf = mBluetoothInCallService.sendDtmf(TEST_DTMF_TONE);
-        Assert.assertFalse(sentDtmf);
-    }
-
-    @Test
-    public void testGetNetworkOperator() throws Exception {
-        PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX);
-        when(mMockCallInfo.getBestPhoneAccount()).thenReturn(fakePhoneAccount);
-
-        String networkOperator = mBluetoothInCallService.getNetworkOperator();
-        Assert.assertEquals(networkOperator, "label0");
-    }
-
-    @Test
-    public void testGetNetworkOperatorNoPhoneAccount() throws Exception {
-        when(mMockCallInfo.getForegroundCall()).thenReturn(null);
-        when(mMockTelephonyManager.getNetworkOperatorName()).thenReturn("label1");
-        mBluetoothInCallService.mTelephonyManager = mMockTelephonyManager;
-
-        String networkOperator = mBluetoothInCallService.getNetworkOperator();
-        Assert.assertEquals(networkOperator, "label1");
-    }
-
-    @Test
-    public void testGetSubscriberNumber() throws Exception {
-        PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX);
-        when(mMockCallInfo.getBestPhoneAccount()).thenReturn(fakePhoneAccount);
-
-        String subscriberNumber = mBluetoothInCallService.getSubscriberNumber();
-        Assert.assertEquals(subscriberNumber, TEST_ACCOUNT_ADDRESS + TEST_ACCOUNT_INDEX);
-    }
-
-    @Test
-    public void testGetSubscriberNumberFallbackToTelephony() throws Exception {
-        String fakeNumber = "8675309";
-        when(mMockCallInfo.getBestPhoneAccount()).thenReturn(null);
-        when(mMockTelephonyManager.getLine1Number())
-                .thenReturn(fakeNumber);
-        mBluetoothInCallService.mTelephonyManager = mMockTelephonyManager;
-
-        String subscriberNumber = mBluetoothInCallService.getSubscriberNumber();
-        Assert.assertEquals(subscriberNumber, fakeNumber);
-    }
-
-    @Test
-    public void testListCurrentCallsOneCall() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        BluetoothCall activeCall = createActiveCall();
-        when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE);
-        calls.add(activeCall);
-        mBluetoothInCallService.onCallAdded(activeCall);
-        when(activeCall.isConference()).thenReturn(false);
-        when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-000"));
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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);
-    }
-
-    @Test
-    public void testListCurrentCallsSilentRinging() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        BluetoothCall silentRingingCall = createActiveCall();
-        when(silentRingingCall.getState()).thenReturn(Call.STATE_RINGING);
-        when(silentRingingCall.isSilentRingingRequested()).thenReturn(true);
-        calls.add(silentRingingCall);
-        mBluetoothInCallService.onCallAdded(silentRingingCall);
-
-        when(silentRingingCall.isConference()).thenReturn(false);
-        when(silentRingingCall.getHandle()).thenReturn(Uri.parse("tel:555-000"));
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(silentRingingCall);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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);
-    }
-
-    @Test
-    public void testConferenceInProgressCDMA() throws Exception {
-        // If two calls are being conferenced and updateHeadsetWithCallState runs while this is
-        // still occurring, it will look like there is an active and held BluetoothCall still while
-        // we are transitioning into a conference.
-        // BluetoothCall has been put into a CDMA "conference" with one BluetoothCall on hold.
-        ArrayList<BluetoothCall>   calls = new ArrayList<>();
-        BluetoothCall parentCall = createActiveCall();
-        final BluetoothCall confCall1 = getMockCall();
-        final BluetoothCall confCall2 = createHeldCall();
-        calls.add(parentCall);
-        calls.add(confCall1);
-        calls.add(confCall2);
-        mBluetoothInCallService.onCallAdded(parentCall);
-        mBluetoothInCallService.onCallAdded(confCall1);
-        mBluetoothInCallService.onCallAdded(confCall2);
-
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        when(confCall1.getState()).thenReturn(Call.STATE_ACTIVE);
-        when(confCall2.getState()).thenReturn(Call.STATE_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);
-        String confCall1Id = confCall1.getTelecomCallId();
-        when(parentCall.getGenericConferenceActiveChildCallId())
-                .thenReturn(confCall1Id);
-        when(parentCall.isConference()).thenReturn(true);
-        List<String> childrenIds = new LinkedList<String>(){{
-            add(confCall1.getTelecomCallId());
-            add(confCall2.getTelecomCallId());
-        }};
-        when(parentCall.getChildrenIds()).thenReturn(childrenIds);
-        //Add links from child calls to parent
-        String parentId = parentCall.getTelecomCallId();
-        when(confCall1.getParentId()).thenReturn(parentId);
-        when(confCall2.getParentId()).thenReturn(parentId);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.queryPhoneState();
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-
-        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true);
-        List<BluetoothCall> children =
-                mBluetoothInCallService.getBluetoothCallsByIds(parentCall.getChildrenIds());
-        mBluetoothInCallService.getCallback(parentCall)
-                .onChildrenChanged(parentCall, children);
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-
-        when(mMockCallInfo.getHeldCall()).thenReturn(null);
-        // Spurious BluetoothCall to onIsConferencedChanged.
-        mBluetoothInCallService.getCallback(parentCall)
-                .onChildrenChanged(parentCall, children);
-        // Make sure the BluetoothCall 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));
-    }
-
-    @Test
-    public void testListCurrentCallsCdmaHold() throws Exception {
-        // BluetoothCall has been put into a CDMA "conference" with one BluetoothCall on hold.
-        List<BluetoothCall> calls = new ArrayList<BluetoothCall>();
-        BluetoothCall parentCall = createActiveCall();
-        final BluetoothCall foregroundCall = getMockCall();
-        final BluetoothCall heldCall = createHeldCall();
-        calls.add(parentCall);
-        calls.add(foregroundCall);
-        calls.add(heldCall);
-        mBluetoothInCallService.onCallAdded(parentCall);
-        mBluetoothInCallService.onCallAdded(foregroundCall);
-        mBluetoothInCallService.onCallAdded(heldCall);
-
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        when(foregroundCall.getState()).thenReturn(Call.STATE_ACTIVE);
-        when(heldCall.getState()).thenReturn(Call.STATE_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);
-
-        String foregroundCallId = foregroundCall.getTelecomCallId();
-        when(parentCall.getGenericConferenceActiveChildCallId()).thenReturn(foregroundCallId);
-        when(parentCall.isConference()).thenReturn(true);
-        List<String> childrenIds = new LinkedList<String>(){{
-            add(foregroundCall.getTelecomCallId());
-            add(heldCall.getTelecomCallId());
-        }};
-        when(parentCall.getChildrenIds()).thenReturn(childrenIds);
-        //Add links from child calls to parent
-        String parentId = parentCall.getTelecomCallId();
-        when(foregroundCall.getParentId()).thenReturn(parentId);
-        when(heldCall.getParentId()).thenReturn(parentId);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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);
-    }
-
-    @Test
-    public void testListCurrentCallsCdmaConference() throws Exception {
-        // BluetoothCall is in a true CDMA conference
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        BluetoothCall parentCall = createActiveCall();
-        final BluetoothCall confCall1 = getMockCall();
-        final BluetoothCall confCall2 = createHeldCall();
-        calls.add(parentCall);
-        calls.add(confCall1);
-        calls.add(confCall2);
-        mBluetoothInCallService.onCallAdded(parentCall);
-        mBluetoothInCallService.onCallAdded(confCall1);
-        mBluetoothInCallService.onCallAdded(confCall2);
-
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        when(confCall1.getState()).thenReturn(Call.STATE_ACTIVE);
-        when(confCall2.getState()).thenReturn(Call.STATE_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);
-        List<String> childrenIds = new LinkedList<String>(){{
-            add(confCall1.getTelecomCallId());
-            add(confCall2.getTelecomCallId());
-        }};
-        when(parentCall.getChildrenIds()).thenReturn(childrenIds);
-        //Add links from child calls to parent
-        String parentId = parentCall.getTelecomCallId();
-        when(confCall1.getParentId()).thenReturn(parentId);
-        when(confCall2.getParentId()).thenReturn(parentId);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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);
-    }
-
-    @Test
-    public void testWaitingCallClccResponse() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        // This test does not define a value for getForegroundCall(), so this ringing
-        // BluetoothCall will be treated as if it is a waiting BluetoothCall
-        // when listCurrentCalls() is invoked.
-        BluetoothCall waitingCall = createRingingCall();
-        calls.add(waitingCall);
-        mBluetoothInCallService.onCallAdded(waitingCall);
-
-        when(waitingCall.isIncoming()).thenReturn(true);
-        when(waitingCall.getGatewayInfo()).thenReturn(
-                new GatewayInfo(null, null, Uri.parse("tel:555-0000")));
-        when(waitingCall.getState()).thenReturn(Call.STATE_RINGING);
-        when(waitingCall.isConference()).thenReturn(false);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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());
-    }
-
-    @Test
-    public void testNewCallClccResponse() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        BluetoothCall newCall = createForegroundCall();
-        calls.add(newCall);
-        mBluetoothInCallService.onCallAdded(newCall);
-
-        when(newCall.getState()).thenReturn(Call.STATE_NEW);
-        when(newCall.isConference()).thenReturn(false);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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());
-    }
-
-    @Test
-    public void testRingingCallClccResponse() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        BluetoothCall ringingCall = createForegroundCall();
-        calls.add(ringingCall);
-        mBluetoothInCallService.onCallAdded(ringingCall);
-
-        when(ringingCall.getState()).thenReturn(Call.STATE_RINGING);
-        when(ringingCall.isIncoming()).thenReturn(true);
-        when(ringingCall.isConference()).thenReturn(false);
-        when(ringingCall.getGatewayInfo()).thenReturn(
-                new GatewayInfo(null, null, Uri.parse("tel:555-0000")));
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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());
-    }
-
-    @Test
-    public void testCallClccCache() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        BluetoothCall ringingCall = createForegroundCall();
-        calls.add(ringingCall);
-        mBluetoothInCallService.onCallAdded(ringingCall);
-
-        when(ringingCall.getState()).thenReturn(Call.STATE_RINGING);
-        when(ringingCall.isIncoming()).thenReturn(true);
-        when(ringingCall.isConference()).thenReturn(false);
-        when(ringingCall.getGatewayInfo()).thenReturn(
-                new GatewayInfo(null, null, Uri.parse("tel:5550000")));
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.listCurrentCalls();
-        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false,
-                "5550000", PhoneNumberUtils.TOA_Unknown);
-
-        // Test Caching of old BluetoothCall indices in clcc
-        when(ringingCall.getState()).thenReturn(Call.STATE_ACTIVE);
-        BluetoothCall newHoldingCall = createHeldCall();
-        calls.add(0, newHoldingCall);
-        mBluetoothInCallService.onCallAdded(newHoldingCall);
-
-        when(newHoldingCall.getState()).thenReturn(Call.STATE_HOLDING);
-        when(newHoldingCall.isIncoming()).thenReturn(true);
-        when(newHoldingCall.isConference()).thenReturn(false);
-        when(newHoldingCall.getGatewayInfo()).thenReturn(
-                new GatewayInfo(null, null, Uri.parse("tel:555-0001")));
-
-        mBluetoothInCallService.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);
-    }
-
-    @Test
-    public void testAlertingCallClccResponse() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        BluetoothCall dialingCall = createForegroundCall();
-        calls.add(dialingCall);
-        mBluetoothInCallService.onCallAdded(dialingCall);
-
-        when(dialingCall.getState()).thenReturn(Call.STATE_DIALING);
-        when(dialingCall.isIncoming()).thenReturn(false);
-        when(dialingCall.isConference()).thenReturn(false);
-        when(dialingCall.getGatewayInfo()).thenReturn(
-                new GatewayInfo(null, null, Uri.parse("tel:555-0000")));
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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());
-    }
-
-    @Test
-    public void testHoldingCallClccResponse() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-        BluetoothCall dialingCall = createForegroundCall();
-        calls.add(dialingCall);
-        mBluetoothInCallService.onCallAdded(dialingCall);
-
-        when(dialingCall.getState()).thenReturn(Call.STATE_DIALING);
-        when(dialingCall.isIncoming()).thenReturn(false);
-        when(dialingCall.isConference()).thenReturn(false);
-        when(dialingCall.getGatewayInfo()).thenReturn(
-                new GatewayInfo(null, null, Uri.parse("tel:555-0000")));
-        BluetoothCall holdingCall = createHeldCall();
-        calls.add(holdingCall);
-        mBluetoothInCallService.onCallAdded(holdingCall);
-
-        when(holdingCall.getState()).thenReturn(Call.STATE_HOLDING);
-        when(holdingCall.isIncoming()).thenReturn(true);
-        when(holdingCall.isConference()).thenReturn(false);
-        when(holdingCall.getGatewayInfo()).thenReturn(
-                new GatewayInfo(null, null, Uri.parse("tel:555-0001")));
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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());
-    }
-
-    @Test
-    public void testListCurrentCallsImsConference() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        BluetoothCall parentCall = createActiveCall();
-        calls.add(parentCall);
-        mBluetoothInCallService.onCallAdded(parentCall);
-
-        addCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.getState()).thenReturn(Call.STATE_ACTIVE);
-        when(parentCall.isIncoming()).thenReturn(true);
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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);
-    }
-
-    @Test
-    public void testListCurrentCallsHeldImsCepConference() throws Exception {
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        BluetoothCall parentCall = createHeldCall();
-        BluetoothCall childCall1 = createActiveCall();
-        BluetoothCall childCall2 = createActiveCall();
-        calls.add(parentCall);
-        calls.add(childCall1);
-        calls.add(childCall2);
-        mBluetoothInCallService.onCallAdded(parentCall);
-        mBluetoothInCallService.onCallAdded(childCall1);
-        mBluetoothInCallService.onCallAdded(childCall2);
-
-        addCallCapability(parentCall, Connection.CAPABILITY_MANAGE_CONFERENCE);
-        String parentId = parentCall.getTelecomCallId();
-        when(childCall1.getParentId()).thenReturn(parentId);
-        when(childCall2.getParentId()).thenReturn(parentId);
-
-        when(parentCall.isConference()).thenReturn(true);
-        when(parentCall.getState()).thenReturn(Call.STATE_HOLDING);
-        when(childCall1.getState()).thenReturn(Call.STATE_ACTIVE);
-        when(childCall2.getState()).thenReturn(Call.STATE_ACTIVE);
-
-        when(parentCall.isIncoming()).thenReturn(true);
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.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);
-    }
-
-    @Test
-    public void testQueryPhoneState() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:5550000"));
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.queryPhoneState();
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    @Test
-    public void testCDMAConferenceQueryState() throws Exception {
-        BluetoothCall parentConfCall = createActiveCall();
-        final BluetoothCall confCall1 = getMockCall();
-        final BluetoothCall confCall2 = getMockCall();
-        mBluetoothInCallService.onCallAdded(confCall1);
-        mBluetoothInCallService.onCallAdded(confCall2);
-        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);
-        List<String> childrenIds = new LinkedList<String>(){{
-            add(confCall1.getTelecomCallId());
-            add(confCall2.getTelecomCallId());
-        }};
-        when(parentConfCall.getChildrenIds()).thenReturn(childrenIds);
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.queryPhoneState();
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @Test
-    public void testProcessChldTypeReleaseHeldRinging() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-        Log.i("BluetoothInCallService", "asdf start " + Integer.toString(ringingCall.hashCode()));
-
-        boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_RELEASEHELD);
-
-        verify(ringingCall).reject(eq(false), nullable(String.class));
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldTypeReleaseHeldHold() throws Exception {
-        BluetoothCall onHoldCall = createHeldCall();
-        boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_RELEASEHELD);
-
-        verify(onHoldCall).disconnect();
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldReleaseActiveRinging() throws Exception {
-        BluetoothCall activeCall = createActiveCall();
-        BluetoothCall ringingCall = createRingingCall();
-
-        boolean didProcess = mBluetoothInCallService.processChld(
-                CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD);
-
-        verify(activeCall).disconnect();
-        verify(ringingCall).answer(any(int.class));
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldReleaseActiveHold() throws Exception {
-        BluetoothCall activeCall = createActiveCall();
-        BluetoothCall heldCall = createHeldCall();
-
-        boolean didProcess = mBluetoothInCallService.processChld(
-                CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD);
-
-        verify(activeCall).disconnect();
-        // BluetoothCall unhold will occur as part of CallsManager auto-unholding
-        // the background BluetoothCall on its own.
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldHoldActiveRinging() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-
-        boolean didProcess = mBluetoothInCallService.processChld(
-                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
-
-        verify(ringingCall).answer(any(int.class));
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldHoldActiveUnhold() throws Exception {
-        BluetoothCall heldCall = createHeldCall();
-
-        boolean didProcess = mBluetoothInCallService.processChld(
-                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
-
-        verify(heldCall).unhold();
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldHoldActiveHold() throws Exception {
-        BluetoothCall activeCall = createActiveCall();
-        addCallCapability(activeCall, Connection.CAPABILITY_HOLD);
-
-        boolean didProcess = mBluetoothInCallService.processChld(
-                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
-
-        verify(activeCall).hold();
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldAddHeldToConfHolding() throws Exception {
-        BluetoothCall activeCall = createActiveCall();
-        addCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-
-        boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_ADDHELDTOCONF);
-
-        verify(activeCall).mergeConference();
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldAddHeldToConf() throws Exception {
-        BluetoothCall activeCall = createActiveCall();
-        removeCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-        BluetoothCall conferenceableCall = getMockCall();
-        ArrayList<String> conferenceableCalls = new ArrayList<>();
-        conferenceableCalls.add(conferenceableCall.getTelecomCallId());
-        mBluetoothInCallService.onCallAdded(conferenceableCall);
-
-        when(activeCall.getConferenceableCalls()).thenReturn(conferenceableCalls);
-
-        boolean didProcess = mBluetoothInCallService.processChld(CHLD_TYPE_ADDHELDTOCONF);
-
-        verify(activeCall).conference(conferenceableCall);
-        Assert.assertTrue(didProcess);
-    }
-
-    @Test
-    public void testProcessChldHoldActiveSwapConference() throws Exception {
-        // Create an active CDMA BluetoothCall with a BluetoothCall on hold
-        // and simulate a swapConference().
-        BluetoothCall parentCall = createActiveCall();
-        final BluetoothCall foregroundCall = getMockCall();
-        final BluetoothCall 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);
-        List<String> childrenIds = new LinkedList<String>(){{
-            add(foregroundCall.getTelecomCallId());
-            add(heldCall.getTelecomCallId());
-        }};
-        when(parentCall.getChildrenIds()).thenReturn(childrenIds);
-
-        clearInvocations(mMockBluetoothHeadset);
-        boolean didProcess = mBluetoothInCallService.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));
-        Assert.assertTrue(didProcess);
-    }
-
-    // Testing the CallsManager Listener Functionality on Bluetooth
-    @Test
-    public void testOnCallAddedRinging() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));
-
-        mBluetoothInCallService.onCallAdded(ringingCall);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    @Test
-    public void testSilentRingingCallState() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-        when(ringingCall.isSilentRingingRequested()).thenReturn(true);
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));
-
-        mBluetoothInCallService.onCallAdded(ringingCall);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallAddedCdmaActiveHold() throws Exception {
-        // BluetoothCall has been put into a CDMA "conference" with one BluetoothCall on hold.
-        BluetoothCall parentCall = createActiveCall();
-        final BluetoothCall foregroundCall = getMockCall();
-        final BluetoothCall heldCall = createHeldCall();
-        addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
-        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
-        when(parentCall.isConference()).thenReturn(true);
-        List<String> childrenIds = new LinkedList<String>(){{
-            add(foregroundCall.getTelecomCallId());
-            add(heldCall.getTelecomCallId());
-        }};
-        when(parentCall.getChildrenIds()).thenReturn(childrenIds);
-
-        mBluetoothInCallService.onCallAdded(parentCall);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallRemoved() throws Exception {
-        BluetoothCall activeCall = createActiveCall();
-        mBluetoothInCallService.onCallAdded(activeCall);
-        doReturn(null).when(mMockCallInfo).getActiveCall();
-        mBluetoothInCallService.onCallRemoved(activeCall);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallStateChangedConnectingCall() throws Exception {
-        BluetoothCall activeCall = getMockCall();
-        BluetoothCall connectingCall = getMockCall();
-        when(connectingCall.getState()).thenReturn(Call.STATE_CONNECTING);
-        ArrayList<BluetoothCall> calls = new ArrayList<>();
-        calls.add(connectingCall);
-        calls.add(activeCall);
-        mBluetoothInCallService.onCallAdded(connectingCall);
-        mBluetoothInCallService.onCallAdded(activeCall);
-        when(mMockCallInfo.getBluetoothCalls()).thenReturn(calls);
-
-        mBluetoothInCallService.getCallback(activeCall)
-                .onStateChanged(activeCall, Call.STATE_HOLDING);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallAddedAudioProcessing() throws Exception {
-        BluetoothCall call = getMockCall();
-        when(call.getState()).thenReturn(Call.STATE_AUDIO_PROCESSING);
-        mBluetoothInCallService.onCallAdded(call);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallStateChangedRingingToAudioProcessing() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));
-
-        mBluetoothInCallService.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(Call.STATE_AUDIO_PROCESSING);
-        when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(null);
-
-        mBluetoothInCallService.getCallback(ringingCall)
-                .onStateChanged(ringingCall, Call.STATE_AUDIO_PROCESSING);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallStateChangedAudioProcessingToSimulatedRinging() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
-        mBluetoothInCallService.onCallAdded(ringingCall);
-        mBluetoothInCallService.getCallback(ringingCall)
-                .onStateChanged(ringingCall, Call.STATE_SIMULATED_RINGING);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallStateChangedAudioProcessingToActive() throws Exception {
-        BluetoothCall activeCall = createActiveCall();
-        when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE);
-        mBluetoothInCallService.onCallAdded(activeCall);
-        mBluetoothInCallService.getCallback(activeCall)
-                .onStateChanged(activeCall, Call.STATE_ACTIVE);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallStateChangedDialing() throws Exception {
-        BluetoothCall activeCall = createActiveCall();
-
-        // make "mLastState" STATE_CONNECTING
-        BluetoothInCallService.CallStateCallback callback =
-                mBluetoothInCallService.new CallStateCallback(Call.STATE_CONNECTING);
-        mBluetoothInCallService.mCallbacks.put(
-                activeCall.getTelecomCallId(), callback);
-
-        mBluetoothInCallService.mCallbacks.get(activeCall.getTelecomCallId())
-                .onStateChanged(activeCall, Call.STATE_DIALING);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallStateChangedAlerting() throws Exception {
-        BluetoothCall outgoingCall = createOutgoingCall();
-        mBluetoothInCallService.onCallAdded(outgoingCall);
-        mBluetoothInCallService.getCallback(outgoingCall)
-                .onStateChanged(outgoingCall, Call.STATE_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));
-    }
-
-    @Test
-    public void testOnCallStateChangedDisconnected() throws Exception {
-        BluetoothCall disconnectedCall = createDisconnectedCall();
-        doReturn(true).when(mMockCallInfo).hasOnlyDisconnectedCalls();
-        mBluetoothInCallService.onCallAdded(disconnectedCall);
-        mBluetoothInCallService.getCallback(disconnectedCall)
-                .onStateChanged(disconnectedCall, Call.STATE_DISCONNECTED);
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallStateChanged() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
-        mBluetoothInCallService.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(mMockCallInfo).getRingingOrSimulatedRingingCall();
-        when(mMockCallInfo.getActiveCall()).thenReturn(ringingCall);
-
-        mBluetoothInCallService.getCallback(ringingCall)
-                .onStateChanged(ringingCall, Call.STATE_ACTIVE);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @Test
-    public void testOnCallStateChangedGSMSwap() throws Exception {
-        BluetoothCall heldCall = createHeldCall();
-        when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
-        mBluetoothInCallService.onCallAdded(heldCall);
-        doReturn(2).when(mMockCallInfo).getNumHeldCalls();
-
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.getCallback(heldCall)
-                .onStateChanged(heldCall, Call.STATE_HOLDING);
-
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(eq(0), eq(2), eq(CALL_STATE_HELD),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    @Test
-    public void testOnParentOnChildrenChanged() 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.
-        BluetoothCall parentCall = createActiveCall();
-        BluetoothCall activeCall = getMockCall();
-        BluetoothCall heldCall = createHeldCall();
-        mBluetoothInCallService.onCallAdded(parentCall);
-        mBluetoothInCallService.onCallAdded(activeCall);
-        mBluetoothInCallService.onCallAdded(heldCall);
-        String parentId = parentCall.getTelecomCallId();
-        when(activeCall.getParentId()).thenReturn(parentId);
-        when(heldCall.getParentId()).thenReturn(parentId);
-
-        ArrayList<String> calls = new ArrayList<>();
-        calls.add(activeCall.getTelecomCallId());
-
-        when(parentCall.getChildrenIds()).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);
-
-        clearInvocations(mMockBluetoothHeadset);
-        // Be sure that onIsConferencedChanged rejects spurious changes during set up of
-        // CDMA "conference"
-        mBluetoothInCallService.getCallback(activeCall)
-                .onParentChanged(activeCall, parentCall);
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-
-        mBluetoothInCallService.getCallback(heldCall)
-                .onParentChanged(heldCall, parentCall);
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-
-        mBluetoothInCallService.getCallback(parentCall)
-                .onChildrenChanged(
-                        parentCall,
-                        mBluetoothInCallService.getBluetoothCallsByIds(calls));
-        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt(), nullable(String.class));
-
-        calls.add(heldCall.getTelecomCallId());
-        mBluetoothInCallService.onCallAdded(heldCall);
-        mBluetoothInCallService.getCallback(parentCall)
-                .onChildrenChanged(
-                        parentCall,
-                        mBluetoothInCallService.getBluetoothCallsByIds(calls));
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128), nullable(String.class));
-    }
-
-    @Test
-    public void testBluetoothAdapterReceiver() throws Exception {
-        BluetoothCall ringingCall = createRingingCall();
-        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:5550000"));
-
-        Intent intent = new Intent();
-        intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON);
-        clearInvocations(mMockBluetoothHeadset);
-        mBluetoothInCallService.mBluetoothAdapterReceiver
-                .onReceive(mBluetoothInCallService, intent);
-
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
-    }
-
-    private void addCallCapability(BluetoothCall call, int capability) {
-        when(call.can(capability)).thenReturn(true);
-    }
-
-    private void removeCallCapability(BluetoothCall call, int capability) {
-        when(call.can(capability)).thenReturn(false);
-    }
-
-    private BluetoothCall createActiveCall() {
-        BluetoothCall call = getMockCall();
-        when(mMockCallInfo.getActiveCall()).thenReturn(call);
-        return call;
-    }
-
-    private BluetoothCall createRingingCall() {
-        BluetoothCall call = getMockCall();
-        Log.i("BluetoothInCallService", "asdf creaete " + Integer.toString(call.hashCode()));
-        when(mMockCallInfo.getRingingOrSimulatedRingingCall()).thenReturn(call);
-        return call;
-    }
-
-    private BluetoothCall createHeldCall() {
-        BluetoothCall call = getMockCall();
-        when(mMockCallInfo.getHeldCall()).thenReturn(call);
-        return call;
-    }
-
-    private BluetoothCall createOutgoingCall() {
-        BluetoothCall call = getMockCall();
-        when(mMockCallInfo.getOutgoingCall()).thenReturn(call);
-        return call;
-    }
-
-    private BluetoothCall createDisconnectedCall() {
-        BluetoothCall call = getMockCall();
-        when(mMockCallInfo.getCallByState(Call.STATE_DISCONNECTED)).thenReturn(call);
-        return call;
-    }
-
-    private BluetoothCall createForegroundCall() {
-        BluetoothCall call = getMockCall();
-        when(mMockCallInfo.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)
-                .setShortDescription("desc" + idx)
-                .setIsEnabled(true)
-                .build();
-    }
-
-    private BluetoothCall getMockCall() {
-        BluetoothCall call = mock(com.android.bluetooth.hfp.BluetoothCall.class);
-        String uuid = UUID.randomUUID().toString();
-        when(call.getTelecomCallId()).thenReturn(uuid);
-        return call;
-    }
-}
diff --git a/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java b/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
index dbbf389..2dd5356 100644
--- a/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
+++ b/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
@@ -185,6 +185,7 @@
         doAnswer(invocation -> mBondedDevices.toArray(new BluetoothDevice[]{})).when(
                 mAdapterService).getBondedDevices();
         // Mock system interface
+        doNothing().when(mSystemInterface).init();
         doNothing().when(mSystemInterface).stop();
         when(mSystemInterface.getHeadsetPhoneState()).thenReturn(mPhoneState);
         when(mSystemInterface.getAudioManager()).thenReturn(mAudioManager);
diff --git a/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java b/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java
index b3deb3a..cf3458c 100644
--- a/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java
+++ b/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java
@@ -116,6 +116,7 @@
             return keys.toArray(new BluetoothDevice[keys.size()]);
         }).when(mAdapterService).getBondedDevices();
         // Mock system interface
+        doNothing().when(mSystemInterface).init();
         doNothing().when(mSystemInterface).stop();
         when(mSystemInterface.getHeadsetPhoneState()).thenReturn(mPhoneState);
         when(mSystemInterface.getAudioManager()).thenReturn(mAudioManager);
