/*
 * Copyright (C) 2012 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.phone;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothHeadsetPhone;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemProperties;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.util.Log;

import com.android.internal.telephony.Call;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.CallManager;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

/**
 * Bluetooth headset manager for the Phone app.
 * @hide
 */
public class BluetoothPhoneService extends Service {
    private static final String TAG = "BluetoothPhoneService";
    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 1)
            && (SystemProperties.getInt("ro.debuggable", 0) == 1);
    private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2);  // even more logging

    private static final String MODIFY_PHONE_STATE = android.Manifest.permission.MODIFY_PHONE_STATE;

    private BluetoothAdapter mAdapter;
    private CallManager mCM;

    private BluetoothHeadset mBluetoothHeadset;

    private PowerManager mPowerManager;

    private WakeLock mStartCallWakeLock;  // held while waiting for the intent to start call

    private PhoneConstants.State mPhoneState = PhoneConstants.State.IDLE;
    CdmaPhoneCallState.PhoneCallState mCdmaThreeWayCallState =
                                            CdmaPhoneCallState.PhoneCallState.IDLE;

    private Call.State mForegroundCallState;
    private Call.State mRingingCallState;
    private CallNumber mRingNumber;
    // number of active calls
    int mNumActive;
    // number of background (held) calls
    int mNumHeld;

    long mBgndEarliestConnectionTime = 0;

    // CDMA specific flag used in context with BT devices having display capabilities
    // to show which Caller is active. This state might not be always true as in CDMA
    // networks if a caller drops off no update is provided to the Phone.
    // This flag is just used as a toggle to provide a update to the BT device to specify
    // which caller is active.
    private boolean mCdmaIsSecondCallActive = false;
    private boolean mCdmaCallsSwapped = false;

    private long[] mClccTimestamps; // Timestamps associated with each clcc index
    private boolean[] mClccUsed;     // Is this clcc index in use

    private static final int GSM_MAX_CONNECTIONS = 6;  // Max connections allowed by GSM
    private static final int CDMA_MAX_CONNECTIONS = 2;  // Max connections allowed by CDMA

    @Override
    public void onCreate() {
        super.onCreate();
        mCM = CallManager.getInstance();
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mAdapter == null) {
            if (VDBG) Log.d(TAG, "mAdapter null");
            return;
        }

        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        mStartCallWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                                                       TAG + ":StartCall");
        mStartCallWakeLock.setReferenceCounted(false);

        mAdapter.getProfileProxy(this, mProfileListener, BluetoothProfile.HEADSET);

        mForegroundCallState = Call.State.IDLE;
        mRingingCallState = Call.State.IDLE;
        mNumActive = 0;
        mNumHeld = 0;
        mRingNumber = new CallNumber("", 0);;

        handlePreciseCallStateChange(null);

        if(VDBG) Log.d(TAG, "registerForServiceStateChanged");
        // register for updates
        mCM.registerForPreciseCallStateChanged(mHandler,
                                               PRECISE_CALL_STATE_CHANGED, null);
        mCM.registerForCallWaiting(mHandler,
                                   PHONE_CDMA_CALL_WAITING, null);
        // TODO(BT) registerForIncomingRing?
        // TODO(BT) registerdisconnection?
        mClccTimestamps = new long[GSM_MAX_CONNECTIONS];
        mClccUsed = new boolean[GSM_MAX_CONNECTIONS];
        for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) {
            mClccUsed[i] = false;
        }
    }

    @Override
    public void onStart(Intent intent, int startId) {
        if (mAdapter == null) {
            Log.w(TAG, "Stopping Bluetooth BluetoothPhoneService Service: device does not have BT");
            stopSelf();
        }
        if (VDBG) Log.d(TAG, "BluetoothPhoneService started");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (DBG) log("Stopping Bluetooth BluetoothPhoneService Service");
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private static final int PRECISE_CALL_STATE_CHANGED = 1;
    private static final int PHONE_CDMA_CALL_WAITING = 2;
    private static final int LIST_CURRENT_CALLS = 3;
    private static final int QUERY_PHONE_STATE = 4;
    private static final int CDMA_SWAP_SECOND_CALL_STATE = 5;
    private static final int CDMA_SET_SECOND_CALL_STATE = 6;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (VDBG) Log.d(TAG, "handleMessage: " + msg.what);
            switch(msg.what) {
                case PRECISE_CALL_STATE_CHANGED:
                case PHONE_CDMA_CALL_WAITING:
                    Connection connection = null;
                    if (((AsyncResult) msg.obj).result instanceof Connection) {
                        connection = (Connection) ((AsyncResult) msg.obj).result;
                    }
                    handlePreciseCallStateChange(connection);
                    break;
                case LIST_CURRENT_CALLS:
                    handleListCurrentCalls();
                    break;
                case QUERY_PHONE_STATE:
                    handleQueryPhoneState();
                    break;
                case CDMA_SWAP_SECOND_CALL_STATE:
                    handleCdmaSwapSecondCallState();
                    break;
                case CDMA_SET_SECOND_CALL_STATE:
                    handleCdmaSetSecondCallState((Boolean) msg.obj);
                    break;
            }
        }
    };

    private void updateBtPhoneStateAfterRadioTechnologyChange() {
        if(VDBG) Log.d(TAG, "updateBtPhoneStateAfterRadioTechnologyChange...");

        //Unregister all events from the old obsolete phone
        mCM.unregisterForPreciseCallStateChanged(mHandler);
        mCM.unregisterForCallWaiting(mHandler);

        //Register all events new to the new active phone
        mCM.registerForPreciseCallStateChanged(mHandler,
                                               PRECISE_CALL_STATE_CHANGED, null);
        mCM.registerForCallWaiting(mHandler,
                                   PHONE_CDMA_CALL_WAITING, null);
    }

    private void handlePreciseCallStateChange(Connection connection) {
        // get foreground call state
        int oldNumActive = mNumActive;
        int oldNumHeld = mNumHeld;
        Call.State oldRingingCallState = mRingingCallState;
        Call.State oldForegroundCallState = mForegroundCallState;
        CallNumber oldRingNumber = mRingNumber;

        Call foregroundCall = mCM.getActiveFgCall();

        if (VDBG)
            Log.d(TAG, " handlePreciseCallStateChange: foreground: " + foregroundCall +
                " background: " + mCM.getFirstActiveBgCall() + " ringing: " +
                mCM.getFirstActiveRingingCall());

        mForegroundCallState = foregroundCall.getState();
        /* if in transition, do not update */
        if (mForegroundCallState == Call.State.DISCONNECTING)
        {
            Log.d(TAG, "handlePreciseCallStateChange. Call disconnecting, wait before update");
            return;
        }
        else
            mNumActive = (mForegroundCallState == Call.State.ACTIVE) ? 1 : 0;

        Call ringingCall = mCM.getFirstActiveRingingCall();
        mRingingCallState = ringingCall.getState();
        mRingNumber = getCallNumber(connection, ringingCall);

        if (mCM.getDefaultPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
            mNumHeld = getNumHeldCdma();
            PhoneGlobals app = PhoneGlobals.getInstance();
            if (app.cdmaPhoneCallState != null) {
                CdmaPhoneCallState.PhoneCallState currCdmaThreeWayCallState =
                        app.cdmaPhoneCallState.getCurrentCallState();
                CdmaPhoneCallState.PhoneCallState prevCdmaThreeWayCallState =
                    app.cdmaPhoneCallState.getPreviousCallState();

                log("CDMA call state: " + currCdmaThreeWayCallState + " prev state:" +
                    prevCdmaThreeWayCallState);

                if ((mBluetoothHeadset != null) &&
                    (mCdmaThreeWayCallState != currCdmaThreeWayCallState)) {
                    // In CDMA, the network does not provide any feedback
                    // to the phone when the 2nd MO call goes through the
                    // stages of DIALING > ALERTING -> ACTIVE we fake the
                    // sequence
                    log("CDMA 3way call state change. mNumActive: " + mNumActive +
                        " mNumHeld: " + mNumHeld + " IsThreeWayCallOrigStateDialing: " +
                        app.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing());
                    if ((currCdmaThreeWayCallState ==
                            CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE)
                                && app.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) {
                        // Mimic dialing, put the call on hold, alerting
                        mBluetoothHeadset.phoneStateChanged(0, mNumHeld,
                            convertCallState(Call.State.IDLE, Call.State.DIALING),
                            mRingNumber.mNumber, mRingNumber.mType);

                        mBluetoothHeadset.phoneStateChanged(0, mNumHeld,
                            convertCallState(Call.State.IDLE, Call.State.ALERTING),
                            mRingNumber.mNumber, mRingNumber.mType);

                    }

                    // In CDMA, the network does not provide any feedback to
                    // the phone when a user merges a 3way call or swaps
                    // between two calls we need to send a CIEV response
                    // indicating that a call state got changed which should
                    // trigger a CLCC update request from the BT client.
                    if (currCdmaThreeWayCallState ==
                            CdmaPhoneCallState.PhoneCallState.CONF_CALL &&
                            prevCdmaThreeWayCallState ==
                              CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
                        log("CDMA 3way conf call. mNumActive: " + mNumActive +
                            " mNumHeld: " + mNumHeld);
                        mBluetoothHeadset.phoneStateChanged(mNumActive, mNumHeld,
                            convertCallState(Call.State.IDLE, mForegroundCallState),
                            mRingNumber.mNumber, mRingNumber.mType);
                    }
                }
                mCdmaThreeWayCallState = currCdmaThreeWayCallState;
            }
        } else {
            mNumHeld = getNumHeldUmts();
        }

        boolean callsSwitched = false;
        if (mCM.getDefaultPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA &&
            mCdmaThreeWayCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
            callsSwitched = mCdmaCallsSwapped;
        } else {
            Call backgroundCall = mCM.getFirstActiveBgCall();
            callsSwitched =
                (mNumHeld == 1 && ! (backgroundCall.getEarliestConnectTime() ==
                    mBgndEarliestConnectionTime));
            mBgndEarliestConnectionTime = backgroundCall.getEarliestConnectTime();
        }

        if (mNumActive != oldNumActive || mNumHeld != oldNumHeld ||
            mRingingCallState != oldRingingCallState ||
            mForegroundCallState != oldForegroundCallState ||
            !mRingNumber.equalTo(oldRingNumber) ||
            callsSwitched) {
            if (mBluetoothHeadset != null) {
                mBluetoothHeadset.phoneStateChanged(mNumActive, mNumHeld,
                    convertCallState(mRingingCallState, mForegroundCallState),
                    mRingNumber.mNumber, mRingNumber.mType);
            }
        }
    }

    private void handleListCurrentCalls() {
        Phone phone = mCM.getDefaultPhone();
        int phoneType = phone.getPhoneType();

        // TODO(BT) handle virtual call

        if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
            listCurrentCallsCdma();
        } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
            listCurrentCallsGsm();
        } else {
            Log.e(TAG, "Unexpected phone type: " + phoneType);
        }
        // end the result
        // when index is 0, other parameter does not matter
        mBluetoothHeadset.clccResponse(0, 0, 0, 0, false, "", 0);
    }

    private void handleQueryPhoneState() {
        if (mBluetoothHeadset != null) {
            mBluetoothHeadset.phoneStateChanged(mNumActive, mNumHeld,
                convertCallState(mRingingCallState, mForegroundCallState),
                mRingNumber.mNumber, mRingNumber.mType);
        }
    }

    private int getNumHeldUmts() {
        int countHeld = 0;
        List<Call> heldCalls = mCM.getBackgroundCalls();

        for (Call call : heldCalls) {
            if (call.getState() == Call.State.HOLDING) {
                countHeld++;
            }
        }
        return countHeld;
    }

    private int getNumHeldCdma() {
        int numHeld = 0;
        PhoneGlobals app = PhoneGlobals.getInstance();
        if (app.cdmaPhoneCallState != null) {
            CdmaPhoneCallState.PhoneCallState curr3WayCallState =
                app.cdmaPhoneCallState.getCurrentCallState();
            CdmaPhoneCallState.PhoneCallState prev3WayCallState =
                app.cdmaPhoneCallState.getPreviousCallState();

            log("CDMA call state: " + curr3WayCallState + " prev state:" +
                prev3WayCallState);
            if (curr3WayCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
                if (prev3WayCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
                    numHeld = 0; //0: no calls held, as now *both* the caller are active
                } else {
                    numHeld = 1; //1: held call and active call, as on answering a
                    // Call Waiting, one of the caller *is* put on hold
                }
            } else if (curr3WayCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
                numHeld = 1; //1: held call and active call, as on make a 3 Way Call
                // the first caller *is* put on hold
            } else {
                numHeld = 0; //0: no calls held as this is a SINGLE_ACTIVE call
            }
        }
        return numHeld;
    }

    private CallNumber getCallNumber(Connection connection, Call call) {
        String number = null;
        int type = 128;
        // find phone number and type
        if (connection == null) {
            connection = call.getEarliestConnection();
            if (connection == null) {
                Log.e(TAG, "Could not get a handle on Connection object for the call");
            }
        }
        if (connection != null) {
            number = connection.getAddress();
            if (number != null) {
                type = PhoneNumberUtils.toaFromString(number);
            }
        }
        if (number == null) {
            number = "";
        }
        return new CallNumber(number, type);
    }

    private class CallNumber
    {
        private String mNumber = null;
        private int mType = 0;

        private CallNumber(String number, int type) {
            mNumber = number;
            mType = type;
        }

        private boolean equalTo(CallNumber callNumber) 
        {
            if (mType != callNumber.mType) return false;
            
            if (mNumber != null && mNumber.compareTo(callNumber.mNumber) == 0) {
                return true;
            }
            return false;
        }
    }

    private BluetoothProfile.ServiceListener mProfileListener =
            new BluetoothProfile.ServiceListener() {
        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            mBluetoothHeadset = (BluetoothHeadset) proxy;
        }
        public void onServiceDisconnected(int profile) {
            mBluetoothHeadset = null;
        }
    };

    private void listCurrentCallsGsm() {
        // Collect all known connections
        // clccConnections isindexed by CLCC index
        Connection[] clccConnections = new Connection[GSM_MAX_CONNECTIONS];
        LinkedList<Connection> newConnections = new LinkedList<Connection>();
        LinkedList<Connection> connections = new LinkedList<Connection>();

        Call foregroundCall = mCM.getActiveFgCall();
        Call backgroundCall = mCM.getFirstActiveBgCall();
        Call ringingCall = mCM.getFirstActiveRingingCall();

        if (ringingCall.getState().isAlive()) {
            connections.addAll(ringingCall.getConnections());
        }
        if (foregroundCall.getState().isAlive()) {
            connections.addAll(foregroundCall.getConnections());
        }
        if (backgroundCall.getState().isAlive()) {
            connections.addAll(backgroundCall.getConnections());
        }

        // Mark connections that we already known about
        boolean clccUsed[] = new boolean[GSM_MAX_CONNECTIONS];
        for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) {
            clccUsed[i] = mClccUsed[i];
            mClccUsed[i] = false;
        }
        for (Connection c : connections) {
            boolean found = false;
            long timestamp = c.getCreateTime();
            for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) {
                if (clccUsed[i] && timestamp == mClccTimestamps[i]) {
                    mClccUsed[i] = true;
                    found = true;
                    clccConnections[i] = c;
                    break;
                }
            }
            if (!found) {
                newConnections.add(c);
            }
        }

        // Find a CLCC index for new connections
        while (!newConnections.isEmpty()) {
            // Find lowest empty index
            int i = 0;
            while (mClccUsed[i]) i++;
            // Find earliest connection
            long earliestTimestamp = newConnections.get(0).getCreateTime();
            Connection earliestConnection = newConnections.get(0);
            for (int j = 0; j < newConnections.size(); j++) {
                long timestamp = newConnections.get(j).getCreateTime();
                if (timestamp < earliestTimestamp) {
                    earliestTimestamp = timestamp;
                    earliestConnection = newConnections.get(j);
                }
            }

            // update
            mClccUsed[i] = true;
            mClccTimestamps[i] = earliestTimestamp;
            clccConnections[i] = earliestConnection;
            newConnections.remove(earliestConnection);
        }

        // Send CLCC response to Bluetooth headset service
        for (int i = 0; i < clccConnections.length; i++) {
            if (mClccUsed[i]) {
                sendClccResponseGsm(i, clccConnections[i]);
            }
        }
    }

    /** Convert a Connection object into a single +CLCC result */
    private void sendClccResponseGsm(int index, Connection connection) {
        int state = convertCallState(connection.getState());
        boolean mpty = false;
        Call call = connection.getCall();
        if (call != null) {
            mpty = call.isMultiparty();
        }

        int direction = connection.isIncoming() ? 1 : 0;

        String number = connection.getAddress();
        int type = -1;
        if (number != null) {
            type = PhoneNumberUtils.toaFromString(number);
        }

        mBluetoothHeadset.clccResponse(index + 1, direction, state, 0, mpty, number, type);
    }

    /** Build the +CLCC result for CDMA
     *  The complexity arises from the fact that we need to maintain the same
     *  CLCC index even as a call moves between states. */
    private synchronized void listCurrentCallsCdma() {
        // In CDMA at one time a user can have only two live/active connections
        Connection[] clccConnections = new Connection[CDMA_MAX_CONNECTIONS];// indexed by CLCC index
        Call foregroundCall = mCM.getActiveFgCall();
        Call ringingCall = mCM.getFirstActiveRingingCall();

        Call.State ringingCallState = ringingCall.getState();
        // If the Ringing Call state is INCOMING, that means this is the very first call
        // hence there should not be any Foreground Call
        if (ringingCallState == Call.State.INCOMING) {
            if (VDBG) log("Filling clccConnections[0] for INCOMING state");
            clccConnections[0] = ringingCall.getLatestConnection();
        } else if (foregroundCall.getState().isAlive()) {
            // Getting Foreground Call connection based on Call state
            if (ringingCall.isRinging()) {
                if (VDBG) log("Filling clccConnections[0] & [1] for CALL WAITING state");
                clccConnections[0] = foregroundCall.getEarliestConnection();
                clccConnections[1] = ringingCall.getLatestConnection();
            } else {
                if (foregroundCall.getConnections().size() <= 1) {
                    // Single call scenario
                    if (VDBG) {
                        log("Filling clccConnections[0] with ForgroundCall latest connection");
                    }
                    clccConnections[0] = foregroundCall.getLatestConnection();
                } else {
                    // Multiple Call scenario. This would be true for both
                    // CONF_CALL and THRWAY_ACTIVE state
                    if (VDBG) {
                        log("Filling clccConnections[0] & [1] with ForgroundCall connections");
                    }
                    clccConnections[0] = foregroundCall.getEarliestConnection();
                    clccConnections[1] = foregroundCall.getLatestConnection();
                }
            }
        }

        // Update the mCdmaIsSecondCallActive flag based on the Phone call state
        if (PhoneGlobals.getInstance().cdmaPhoneCallState.getCurrentCallState()
                == CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE) {
            Message msg = mHandler.obtainMessage(CDMA_SET_SECOND_CALL_STATE, false);
            mHandler.sendMessage(msg);
        } else if (PhoneGlobals.getInstance().cdmaPhoneCallState.getCurrentCallState()
                == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
            Message msg = mHandler.obtainMessage(CDMA_SET_SECOND_CALL_STATE, true);
            mHandler.sendMessage(msg);
        }

        // send CLCC result
        for (int i = 0; (i < clccConnections.length) && (clccConnections[i] != null); i++) {
            sendClccResponseCdma(i, clccConnections[i]);
        }
    }

    /** Send ClCC results for a Connection object for CDMA phone */
    private void sendClccResponseCdma(int index, Connection connection) {
        int state;
        PhoneGlobals app = PhoneGlobals.getInstance();
        CdmaPhoneCallState.PhoneCallState currCdmaCallState =
                app.cdmaPhoneCallState.getCurrentCallState();
        CdmaPhoneCallState.PhoneCallState prevCdmaCallState =
                app.cdmaPhoneCallState.getPreviousCallState();

        if ((prevCdmaCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE)
                && (currCdmaCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL)) {
            // If the current state is reached after merging two calls
            // we set the state of all the connections as ACTIVE
            state = CALL_STATE_ACTIVE;
        } else {
            Call.State callState = connection.getState();
            switch (callState) {
            case ACTIVE:
                // For CDMA since both the connections are set as active by FW after accepting
                // a Call waiting or making a 3 way call, we need to set the state specifically
                // to ACTIVE/HOLDING based on the mCdmaIsSecondCallActive flag. This way the
                // CLCC result will allow BT devices to enable the swap or merge options
                if (index == 0) { // For the 1st active connection
                    state = mCdmaIsSecondCallActive ? CALL_STATE_HELD : CALL_STATE_ACTIVE;
                } else { // for the 2nd active connection
                    state = mCdmaIsSecondCallActive ? CALL_STATE_ACTIVE : CALL_STATE_HELD;
                }
                break;
            case HOLDING:
                state = CALL_STATE_HELD;
                break;
            case DIALING:
                state = CALL_STATE_DIALING;
                break;
            case ALERTING:
                state = CALL_STATE_ALERTING;
                break;
            case INCOMING:
                state = CALL_STATE_INCOMING;
                break;
            case WAITING:
                state = CALL_STATE_WAITING;
                break;
            default:
                Log.e(TAG, "bad call state: " + callState);
                return;
            }
        }

        boolean mpty = false;
        if (currCdmaCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
            if (prevCdmaCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
                // If the current state is reached after merging two calls
                // we set the multiparty call true.
                mpty = true;
            } // else
                // CALL_CONF state is not from merging two calls, but from
                // accepting the second call. In this case first will be on
                // hold in most cases but in some cases its already merged.
                // However, we will follow the common case and the test case
                // as per Bluetooth SIG PTS
        }

        int direction = connection.isIncoming() ? 1 : 0;

        String number = connection.getAddress();
        int type = -1;
        if (number != null) {
            type = PhoneNumberUtils.toaFromString(number);
        } else {
            number = "";
        }

        mBluetoothHeadset.clccResponse(index + 1, direction, state, 0, mpty, number, type);
    }

    private void handleCdmaSwapSecondCallState() {
        if (VDBG) log("cdmaSwapSecondCallState: Toggling mCdmaIsSecondCallActive");
        mCdmaIsSecondCallActive = !mCdmaIsSecondCallActive;
        mCdmaCallsSwapped = true;
    }

    private void handleCdmaSetSecondCallState(boolean state) {
        if (VDBG) log("cdmaSetSecondCallState: Setting mCdmaIsSecondCallActive to " + state);
        mCdmaIsSecondCallActive = state;

        if (!mCdmaIsSecondCallActive) {
            mCdmaCallsSwapped = false;
        }
    }

    private final IBluetoothHeadsetPhone.Stub mBinder = new IBluetoothHeadsetPhone.Stub() {
        public boolean answerCall() {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            return PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
        }

        public boolean hangupCall() {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            if (mCM.hasActiveFgCall()) {
                return PhoneUtils.hangupActiveCall(mCM.getActiveFgCall());
            } else if (mCM.hasActiveRingingCall()) {
                return PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());
            } else if (mCM.hasActiveBgCall()) {
                return PhoneUtils.hangupHoldingCall(mCM.getFirstActiveBgCall());
            }
            // TODO(BT) handle virtual voice call
            return false;
        }

        public boolean sendDtmf(int dtmf) {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            return mCM.sendDtmf((char) dtmf);
        }

        public boolean processChld(int chld) {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            Phone phone = mCM.getDefaultPhone();
            int phoneType = phone.getPhoneType();
            Call ringingCall = mCM.getFirstActiveRingingCall();
            Call backgroundCall = mCM.getFirstActiveBgCall();

            if (chld == CHLD_TYPE_RELEASEHELD) {
                if (ringingCall.isRinging()) {
                    return PhoneUtils.hangupRingingCall(ringingCall);
                } else {
                    return PhoneUtils.hangupHoldingCall(backgroundCall);
                }
            } else if (chld == CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD) {
                if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                    if (ringingCall.isRinging()) {
                        // Hangup the active call and then answer call waiting call.
                        if (VDBG) log("CHLD:1 Callwaiting Answer call");
                        PhoneUtils.hangupRingingAndActive(phone);
                    } else {
                        // If there is no Call waiting then just hangup
                        // the active call. In CDMA this mean that the complete
                        // call session would be ended
                        if (VDBG) log("CHLD:1 Hangup Call");
                        PhoneUtils.hangup(PhoneGlobals.getInstance().mCM);
                    }
                    return true;
                } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                    // Hangup active call, answer held call
                    return PhoneUtils.answerAndEndActive(PhoneGlobals.getInstance().mCM, ringingCall);
                } else {
                    Log.e(TAG, "bad phone type: " + phoneType);
                    return false;
                }
            } else if (chld == CHLD_TYPE_HOLDACTIVE_ACCEPTHELD) {
                if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                    // For CDMA, the way we switch to a new incoming call is by
                    // calling PhoneUtils.answerCall(). switchAndHoldActive() won't
                    // properly update the call state within telephony.
                    // If the Phone state is already in CONF_CALL then we simply send
                    // a flash cmd by calling switchHoldingAndActive()
                    if (ringingCall.isRinging()) {
                        if (VDBG) log("CHLD:2 Callwaiting Answer call");
                        PhoneUtils.answerCall(ringingCall);
                        PhoneUtils.setMute(false);
                        // Setting the second callers state flag to TRUE (i.e. active)
                        cdmaSetSecondCallState(true);
                        return true;
                    } else if (PhoneGlobals.getInstance().cdmaPhoneCallState
                               .getCurrentCallState()
                               == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
                        if (VDBG) log("CHLD:2 Swap Calls");
                        PhoneUtils.switchHoldingAndActive(backgroundCall);
                        // Toggle the second callers active state flag
                        cdmaSwapSecondCallState();
                        return true;
                    }
                    Log.e(TAG, "CDMA fail to do hold active and accept held");
                    return false;
                } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                    PhoneUtils.switchHoldingAndActive(backgroundCall);
                    return true;
                } else {
                    Log.e(TAG, "Unexpected phone type: " + phoneType);
                    return false;
                }
            } else if (chld == CHLD_TYPE_ADDHELDTOCONF) {
                if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                    CdmaPhoneCallState.PhoneCallState state =
                        PhoneGlobals.getInstance().cdmaPhoneCallState.getCurrentCallState();
                    // For CDMA, we need to check if the call is in THRWAY_ACTIVE state
                    if (state == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
                        if (VDBG) log("CHLD:3 Merge Calls");
                        PhoneUtils.mergeCalls();
                        return true;
                    }   else if (state == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
                        // State is CONF_CALL already and we are getting a merge call
                        // This can happen when CONF_CALL was entered from a Call Waiting
                        // TODO(BT)
                        return false;
                    }
                    Log.e(TAG, "GSG no call to add conference");
                    return false;
                } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                    if (mCM.hasActiveFgCall() && mCM.hasActiveBgCall()) {
                        PhoneUtils.mergeCalls();
                        return true;
                    } else {
                        Log.e(TAG, "GSG no call to merge");
                        return false;
                    }
                } else {
                    Log.e(TAG, "Unexpected phone type: " + phoneType);
                    return false;
                }                
            } else {
                Log.e(TAG, "bad CHLD value: " + chld);
                return false;
            }
        }

        public String getNetworkOperator() {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            return mCM.getDefaultPhone().getServiceState().getOperatorAlphaLong();
        }

        public String getSubscriberNumber() {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            return mCM.getDefaultPhone().getLine1Number();
        }

        public boolean listCurrentCalls() {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            Message msg = Message.obtain(mHandler, LIST_CURRENT_CALLS);
            mHandler.sendMessage(msg);
            return true;
        }

        public boolean queryPhoneState() {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            Message msg = Message.obtain(mHandler, QUERY_PHONE_STATE);
            mHandler.sendMessage(msg);
            return true;
        }

        public void updateBtHandsfreeAfterRadioTechnologyChange() {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            if (VDBG) Log.d(TAG, "updateBtHandsfreeAfterRadioTechnologyChange...");
            updateBtPhoneStateAfterRadioTechnologyChange();
        }

        public void cdmaSwapSecondCallState() {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            Message msg = Message.obtain(mHandler, CDMA_SWAP_SECOND_CALL_STATE);
            mHandler.sendMessage(msg);
        }

        public void cdmaSetSecondCallState(boolean state) {
            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
            Message msg = mHandler.obtainMessage(CDMA_SET_SECOND_CALL_STATE, state);
            mHandler.sendMessage(msg);
        }
    };

    // match up with bthf_call_state_t of bt_hf.h
    final static int CALL_STATE_ACTIVE = 0;
    final static int CALL_STATE_HELD = 1;
    final static int CALL_STATE_DIALING = 2;
    final static int CALL_STATE_ALERTING = 3;
    final static int CALL_STATE_INCOMING = 4;
    final static int CALL_STATE_WAITING = 5;
    final static int CALL_STATE_IDLE = 6;

    // match up with bthf_chld_type_t of bt_hf.h
    final static int CHLD_TYPE_RELEASEHELD = 0;
    final static int CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD = 1;
    final static int CHLD_TYPE_HOLDACTIVE_ACCEPTHELD = 2;
    final static int CHLD_TYPE_ADDHELDTOCONF = 3;

     /* Convert telephony phone call state into hf hal call state */
    static int convertCallState(Call.State ringingState, Call.State foregroundState) {
        if ((ringingState == Call.State.INCOMING) ||
            (ringingState == Call.State.WAITING) )
            return CALL_STATE_INCOMING;
        else if (foregroundState == Call.State.DIALING)
            return CALL_STATE_DIALING;
        else if (foregroundState == Call.State.ALERTING)
            return CALL_STATE_ALERTING;
        else
            return CALL_STATE_IDLE;
    }

    static int convertCallState(Call.State callState) {
        switch (callState) {
        case IDLE:
        case DISCONNECTED:
        case DISCONNECTING:
            return CALL_STATE_IDLE;
        case ACTIVE:
            return CALL_STATE_ACTIVE;
        case HOLDING:
            return CALL_STATE_HELD;
        case DIALING:
            return CALL_STATE_DIALING;
        case ALERTING:
            return CALL_STATE_ALERTING;
        case INCOMING:
            return CALL_STATE_INCOMING;
        case WAITING:
            return CALL_STATE_WAITING;
        default:
            Log.e(TAG, "bad call state: " + callState);
            return CALL_STATE_IDLE;
        }
    }

    private static void log(String msg) {
        Log.d(TAG, msg);
    }
}
