/*
 * Copyright (C) 2006 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.BluetoothAudioGateway;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.HeadsetBase;
import android.bluetooth.IBluetoothHeadset;
import android.os.ParcelUuid;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;

import com.android.internal.telephony.Call;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Set;

/**
 * Provides Bluetooth Headset and Handsfree profile, as a service in
 * the Phone application.
 * @hide
 */
public class BluetoothHeadsetService extends Service {
    private static final String TAG = "BT HSHFP";
    private static final boolean DBG = true;

    private static final String PREF_NAME = BluetoothHeadsetService.class.getSimpleName();
    private static final String PREF_LAST_HEADSET = "lastHeadsetAddress";

    private static final int PHONE_STATE_CHANGED = 1;

    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;

    private static boolean sHasStarted = false;

    private BluetoothDevice mDeviceSdpQuery;
    private BluetoothAdapter mAdapter;
    private PowerManager mPowerManager;
    private BluetoothAudioGateway mAg;
    private HeadsetBase mHeadset;
    private int mState;
    private int mHeadsetType;
    private BluetoothHandsfree mBtHandsfree;
    private BluetoothDevice mRemoteDevice;
    private LinkedList<BluetoothDevice> mAutoConnectQueue;
    private Call mForegroundCall;
    private Call mRingingCall;
    private Phone mPhone;

    private final HeadsetPriority mHeadsetPriority = new HeadsetPriority();

    public BluetoothHeadsetService() {
        mState = BluetoothHeadset.STATE_DISCONNECTED;
        mHeadsetType = BluetoothHandsfree.TYPE_UNKNOWN;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        mBtHandsfree = PhoneApp.getInstance().getBluetoothHandsfree();
        mAg = new BluetoothAudioGateway(mAdapter);
        mPhone = PhoneFactory.getDefaultPhone();
        mRingingCall = mPhone.getRingingCall();
        mForegroundCall = mPhone.getForegroundCall();
        if (mAdapter.isEnabled()) {
            mHeadsetPriority.load();
        }
        IntentFilter filter = new IntentFilter(
                BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
        filter.addAction(BluetoothDevice.ACTION_UUID);
        registerReceiver(mBluetoothReceiver, filter);
   }

    @Override
    public void onStart(Intent intent, int startId) {
         if (mAdapter == null) {
            Log.w(TAG, "Stopping BluetoothHeadsetService: device does not have BT");
            stopSelf();
        } else {
            if (!sHasStarted) {
                if (DBG) log("Starting BluetoothHeadsetService");
                if (mAdapter.isEnabled()) {
                    mAg.start(mIncomingConnectionHandler);
                    mBtHandsfree.onBluetoothEnabled();
                    // BT might have only just started, wait 6 seconds until
                    // SDP records are registered before reconnecting headset
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(RECONNECT_LAST_HEADSET),
                            6000);
                }
                sHasStarted = true;
            }
        }
    }

    private final Handler mIncomingConnectionHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            BluetoothAudioGateway.IncomingConnectionInfo info =
                    (BluetoothAudioGateway.IncomingConnectionInfo)msg.obj;
            int type = BluetoothHandsfree.TYPE_UNKNOWN;
            switch(msg.what) {
            case BluetoothAudioGateway.MSG_INCOMING_HEADSET_CONNECTION:
                type = BluetoothHandsfree.TYPE_HEADSET;
                break;
            case BluetoothAudioGateway.MSG_INCOMING_HANDSFREE_CONNECTION:
                type = BluetoothHandsfree.TYPE_HANDSFREE;
                break;
            }

            Log.i(TAG, "Incoming rfcomm (" + BluetoothHandsfree.typeToString(type) +
                  ") connection from " + info.mRemoteDevice + "on channel " + info.mRfcommChan);

            int priority = BluetoothHeadset.PRIORITY_OFF;
            HeadsetBase headset;
            try {
                priority = mBinder.getPriority(info.mRemoteDevice);
            } catch (RemoteException e) {}
            if (priority <= BluetoothHeadset.PRIORITY_OFF) {
                Log.i(TAG, "Rejecting incoming connection because priority = " + priority);

                headset = new HeadsetBase(mPowerManager, mAdapter, info.mRemoteDevice,
                        info.mSocketFd, info.mRfcommChan, null);
                headset.disconnect();
                return;
            }
            switch (mState) {
            case BluetoothHeadset.STATE_DISCONNECTED:
                // headset connecting us, lets join
                mRemoteDevice = info.mRemoteDevice;
                setState(BluetoothHeadset.STATE_CONNECTING);
                headset = new HeadsetBase(mPowerManager, mAdapter, mRemoteDevice, info.mSocketFd,
                        info.mRfcommChan, mConnectedStatusHandler);
                mHeadsetType = type;

                mConnectingStatusHandler.obtainMessage(RFCOMM_CONNECTED, headset).sendToTarget();

                break;
            case BluetoothHeadset.STATE_CONNECTING:
                if (!info.mRemoteDevice.equals(mRemoteDevice)) {
                    // different headset, ignoring
                    Log.i(TAG, "Already attempting connect to " + mRemoteDevice +
                          ", disconnecting " + info.mRemoteDevice);

                    headset = new HeadsetBase(mPowerManager, mAdapter, info.mRemoteDevice,
                            info.mSocketFd, info.mRfcommChan, null);
                    headset.disconnect();
                }
                // If we are here, we are in danger of a race condition
                // incoming rfcomm connection, but we are also attempting an
                // outgoing connection. Lets try and interrupt the outgoing
                // connection.
                Log.i(TAG, "Incoming and outgoing connections to " + info.mRemoteDevice +
                            ". Cancel outgoing connection.");
                if (mConnectThread != null) {
                    mConnectThread.interrupt();
                    mConnectThread = null;
                }

                // Now continue with new connection, including calling callback
                mHeadset = new HeadsetBase(mPowerManager, mAdapter, mRemoteDevice,
                        info.mSocketFd, info.mRfcommChan, mConnectedStatusHandler);
                mHeadsetType = type;

                setState(BluetoothHeadset.STATE_CONNECTED, BluetoothHeadset.RESULT_SUCCESS);
                mBtHandsfree.connectHeadset(mHeadset, mHeadsetType);

                if (DBG) log("Successfully used incoming connection");
                break;
            case BluetoothHeadset.STATE_CONNECTED:
                Log.i(TAG, "Already connected to " + mRemoteDevice + ", disconnecting " +
                      info.mRemoteDevice);

                headset = new HeadsetBase(mPowerManager, mAdapter, info.mRemoteDevice,
                        info.mSocketFd, info.mRfcommChan, null);
                headset.disconnect();
                break;
            }
        }
    };

    private synchronized void autoConnectHeadset() {
        if (DBG && debugDontReconnect()) {
            return;
        }
        if (mAdapter.isEnabled()) {
            try {
                mBinder.connectHeadset(null);
            } catch (RemoteException e) {}
        }
    }

    private final BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice device =
                    intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            if ((mState == BluetoothHeadset.STATE_CONNECTED ||
                    mState == BluetoothHeadset.STATE_CONNECTING) &&
                    action.equals(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED) &&
                    device.equals(mRemoteDevice)) {
                try {
                    mBinder.disconnectHeadset();
                } catch (RemoteException e) {}
            } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                switch (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
                                           BluetoothAdapter.ERROR)) {
                case BluetoothAdapter.STATE_ON:
                    mHeadsetPriority.load();
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(RECONNECT_LAST_HEADSET), 8000);
                    mAg.start(mIncomingConnectionHandler);
                    mBtHandsfree.onBluetoothEnabled();
                    break;
                case BluetoothAdapter.STATE_TURNING_OFF:
                    mBtHandsfree.onBluetoothDisabled();
                    mAg.stop();
                    setState(BluetoothHeadset.STATE_DISCONNECTED, BluetoothHeadset.RESULT_FAILURE,
                             BluetoothHeadset.LOCAL_DISCONNECT);
                    break;
                }
            } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
                int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                                                   BluetoothDevice.ERROR);
                switch(bondState) {
                case BluetoothDevice.BOND_BONDED:
                    if (mHeadsetPriority.get(device) == BluetoothHeadset.PRIORITY_UNDEFINED) {
                        mHeadsetPriority.set(device, BluetoothHeadset.PRIORITY_ON);
                    }
                    break;
                case BluetoothDevice.BOND_NONE:
                    mHeadsetPriority.set(device, BluetoothHeadset.PRIORITY_UNDEFINED);
                    break;
                }
            } else if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                if (streamType == AudioManager.STREAM_BLUETOOTH_SCO) {
                    mBtHandsfree.sendScoGainUpdate(intent.getIntExtra(
                            AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0));
                }

            } else if (action.equals(BluetoothDevice.ACTION_UUID)) {
                if (device.equals(mDeviceSdpQuery)) {
                    // We have got SDP records for the device we are interested in.
                    getSdpRecordsAndConnect();
                }
            }
        }
    };

    private static final int RECONNECT_LAST_HEADSET = 1;
    private static final int CONNECT_HEADSET_DELAYED = 2;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case RECONNECT_LAST_HEADSET:
                autoConnectHeadset();
                break;
            case CONNECT_HEADSET_DELAYED:
                getSdpRecordsAndConnect();
                break;
            }
        }
    };

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

    // ------------------------------------------------------------------
    // Bluetooth Headset Connect
    // ------------------------------------------------------------------
    private static final int RFCOMM_CONNECTED             = 1;
    private static final int RFCOMM_ERROR                 = 2;

    private long mTimestamp;

    /**
     * Thread for RFCOMM connection
     * Messages are sent to mConnectingStatusHandler as connection progresses.
     */
    private RfcommConnectThread mConnectThread;
    private class RfcommConnectThread extends Thread {
        private BluetoothDevice device;
        private int channel;
        private int type;

        private static final int EINTERRUPT = -1000;
        private static final int ECONNREFUSED = -111;

        public RfcommConnectThread(BluetoothDevice device, int channel, int type) {
            super();
            this.device = device;
            this.channel = channel;
            this.type = type;
        }

        private int waitForConnect(HeadsetBase headset) {
            // Try to connect for 20 seconds
            int result = 0;
            for (int i=0; i < 40 && result == 0; i++) {
                // waitForAsyncConnect returns 0 on timeout, 1 on success, < 0 on error.
                result = headset.waitForAsyncConnect(500, mConnectedStatusHandler);
                if (isInterrupted()) {
                    headset.disconnect();
                    return EINTERRUPT;
                }
            }
            return result;
        }

        @Override
        public void run() {
            long timestamp;

            timestamp = System.currentTimeMillis();
            HeadsetBase headset = new HeadsetBase(mPowerManager, mAdapter, device, channel);

            int result = waitForConnect(headset);

            if (result != EINTERRUPT && result != 1) {
                if (result == ECONNREFUSED && mDeviceSdpQuery == null) {
                    // The rfcomm channel number might have changed, do SDP
                    // query and try to connect again.
                    mDeviceSdpQuery = mRemoteDevice;
                    device.fetchUuidsWithSdp();
                    mConnectThread = null;
                    return;
                } else {
                    Log.i(TAG, "Trying to connect to rfcomm socket again after 1 sec");
                    try {
                      sleep(1000);  // 1 second
                    } catch (InterruptedException e) {}
                }
                result = waitForConnect(headset);
            }

            mDeviceSdpQuery = null;
            if (result == EINTERRUPT) return;

            if (DBG) log("RFCOMM connection attempt took " +
                  (System.currentTimeMillis() - timestamp) + " ms");
            if (isInterrupted()) {
                headset.disconnect();
                return;
            }
            if (result < 0) {
                Log.w(TAG, "headset.waitForAsyncConnect() error: " + result);
                mConnectingStatusHandler.obtainMessage(RFCOMM_ERROR).sendToTarget();
                return;
            } else if (result == 0) {
                mConnectingStatusHandler.obtainMessage(RFCOMM_ERROR).sendToTarget();
                Log.w(TAG, "mHeadset.waitForAsyncConnect() error: " + result + "(timeout)");
                return;
            } else {
                mConnectingStatusHandler.obtainMessage(RFCOMM_CONNECTED, headset).sendToTarget();
            }
        }
    }

    /**
     * Receives events from mConnectThread back in the main thread.
     */
    private final Handler mConnectingStatusHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (mState != BluetoothHeadset.STATE_CONNECTING) {
                return;  // stale events
            }

            switch (msg.what) {
            case RFCOMM_ERROR:
                if (DBG) log("Rfcomm error");
                mConnectThread = null;
                setState(BluetoothHeadset.STATE_DISCONNECTED, BluetoothHeadset.RESULT_FAILURE,
                         BluetoothHeadset.LOCAL_DISCONNECT);
                break;
            case RFCOMM_CONNECTED:
                if (DBG) log("Rfcomm connected");
                mConnectThread = null;
                mHeadset = (HeadsetBase)msg.obj;
                setState(BluetoothHeadset.STATE_CONNECTED, BluetoothHeadset.RESULT_SUCCESS);

                mBtHandsfree.connectHeadset(mHeadset, mHeadsetType);
                break;
            }
        }
    };

    /**
     * Receives events from a connected RFCOMM socket back in the main thread.
     */
    private final Handler mConnectedStatusHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case HeadsetBase.RFCOMM_DISCONNECTED:
                mBtHandsfree.resetAtState();
                setState(BluetoothHeadset.STATE_DISCONNECTED, BluetoothHeadset.RESULT_FAILURE,
                         BluetoothHeadset.REMOTE_DISCONNECT);
                break;
            }
        }
    };

    private void setState(int state) {
        setState(state, BluetoothHeadset.RESULT_SUCCESS);
    }

    private void setState(int state, int result) {
        setState(state, result, -1);
    }

    private synchronized void setState(int state, int result, int initiator) {
        if (state != mState) {
            if (DBG) log("Headset state " + mState + " -> " + state + ", result = " + result);
            if (mState == BluetoothHeadset.STATE_CONNECTED) {
                mBtHandsfree.disconnectHeadset();
            }
            Intent intent = new Intent(BluetoothHeadset.ACTION_STATE_CHANGED);
            intent.putExtra(BluetoothHeadset.EXTRA_PREVIOUS_STATE, mState);
            mState = state;
            intent.putExtra(BluetoothHeadset.EXTRA_STATE, mState);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
            // Add Extra EXTRA_DISCONNECT_INITIATOR for DISCONNECTED state
            if (mState == BluetoothHeadset.STATE_DISCONNECTED) {
                if (initiator == -1) {
                    log("Headset Disconnected Intent without Disconnect Initiator extra");
                } else {
                    intent.putExtra(BluetoothHeadset.EXTRA_DISCONNECT_INITIATOR,
                                    initiator);
                }
            }
            sendBroadcast(intent, BLUETOOTH_PERM);
            if (mState == BluetoothHeadset.STATE_DISCONNECTED) {
                mHeadset = null;
                mRemoteDevice = null;
                mHeadsetType = BluetoothHandsfree.TYPE_UNKNOWN;
                if (mAutoConnectQueue != null) {
                    doNextAutoConnect();
                }
            } else if (mState == BluetoothHeadset.STATE_CONNECTING) {
                // Set the priority to AUTO_CONNECT
                mHeadsetPriority.set(mRemoteDevice, BluetoothHeadset.PRIORITY_AUTO_CONNECT);
            } else if (mState == BluetoothHeadset.STATE_CONNECTED) {
                mAutoConnectQueue = null;  // cancel further auto-connection
                mHeadsetPriority.bump(mRemoteDevice);
            }
        }
    }

    private void getSdpRecordsAndConnect() {
        ParcelUuid[] uuids = mRemoteDevice.getUuids();
        if (uuids != null) {
            if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) {
                log("SDP UUID: TYPE_HANDSFREE");
                mHeadsetType = BluetoothHandsfree.TYPE_HANDSFREE;
                int channel = mRemoteDevice.getServiceChannel(BluetoothUuid.Handsfree);
                mConnectThread = new RfcommConnectThread(mRemoteDevice, channel, mHeadsetType);
                mConnectThread.start();
                return;
            } else if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP)) {
                log("SDP UUID: TYPE_HEADSET");
                mHeadsetType = BluetoothHandsfree.TYPE_HEADSET;
                int channel = mRemoteDevice.getServiceChannel(BluetoothUuid.HSP);
                mConnectThread = new RfcommConnectThread(mRemoteDevice, channel, mHeadsetType);
                mConnectThread.start();
                return;
            }
        }
        log("SDP UUID: TYPE_UNKNOWN");
        mHeadsetType = BluetoothHandsfree.TYPE_UNKNOWN;
        setState(BluetoothHeadset.STATE_DISCONNECTED,
                BluetoothHeadset.RESULT_FAILURE, BluetoothHeadset.LOCAL_DISCONNECT);
        return;
    }

    private synchronized boolean doNextAutoConnect() {
        if (mAutoConnectQueue == null || mAutoConnectQueue.size() == 0) {
            mAutoConnectQueue = null;
            return false;
        }
        mRemoteDevice = mAutoConnectQueue.removeFirst();
        // Don't auto connect with docks if we are docked with the dock.
        if (isPhoneDocked(mRemoteDevice)) return doNextAutoConnect();

        if (DBG) log("pulled " + mRemoteDevice + " off auto-connect queue");
        setState(BluetoothHeadset.STATE_CONNECTING);
        getSdpRecordsAndConnect();

        return true;
    }

    private boolean isPhoneDocked(BluetoothDevice autoConnectDevice) {
        // This works only because these broadcast intents are "sticky"
        Intent i = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
        if (i != null) {
            int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
            if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
                BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (device != null && autoConnectDevice.equals(device)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Handlers for incoming service calls
     */
    private final IBluetoothHeadset.Stub mBinder = new IBluetoothHeadset.Stub() {
        public int getState() {
            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
            return mState;
        }
        public BluetoothDevice getCurrentHeadset() {
            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
            if (mState == BluetoothHeadset.STATE_DISCONNECTED) {
                return null;
            }
            return mRemoteDevice;
        }
        public boolean connectHeadset(BluetoothDevice device) {
            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                           "Need BLUETOOTH_ADMIN permission");
            synchronized (BluetoothHeadsetService.this) {
                if (mState == BluetoothHeadset.STATE_CONNECTED ||
                    mState == BluetoothHeadset.STATE_CONNECTING) {
                    Log.w(TAG, "connectHeadset(" + device + "): failed: already in state " +
                          mState + " with headset " + mRemoteDevice);
                    return false;
                }
                if (device == null) {
                    mAutoConnectQueue = mHeadsetPriority.getSorted();
                    return doNextAutoConnect();
                }
                mRemoteDevice = device;
                setState(BluetoothHeadset.STATE_CONNECTING);
                if (mRemoteDevice.getUuids() == null) {
                    // We might not have got the UUID change notification from
                    // Bluez yet, if we have just paired. Try after 1.5 secs.
                    mHandler.sendMessageDelayed(
                            mHandler.obtainMessage(CONNECT_HEADSET_DELAYED), 1500);
                } else {
                    getSdpRecordsAndConnect();
                }
            }
            return true;
        }
        public boolean isConnected(BluetoothDevice device) {
            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
            return mState == BluetoothHeadset.STATE_CONNECTED && mRemoteDevice.equals(device);
        }
        public void disconnectHeadset() {
            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                           "Need BLUETOOTH_ADMIN permission");
            synchronized (BluetoothHeadsetService.this) {
                switch (mState) {
                case BluetoothHeadset.STATE_CONNECTING:
                    if (mConnectThread != null) {
                        // cancel the connection thread
                        mConnectThread.interrupt();
                        try {
                            mConnectThread.join();
                        } catch (InterruptedException e) {
                            Log.e(TAG, "Connection cancelled twice?", e);
                        }
                        mConnectThread = null;
                    }
                    if (mHeadset != null) {
                        mHeadset.disconnect();
                        mHeadset = null;
                    }
                    setState(BluetoothHeadset.STATE_DISCONNECTED,
                             BluetoothHeadset.RESULT_CANCELED,
                             BluetoothHeadset.LOCAL_DISCONNECT);
                    break;
                case BluetoothHeadset.STATE_CONNECTED:
                    // Send a dummy battery level message to force headset
                    // out of sniff mode so that it will immediately notice
                    // the disconnection. We are currently sending it for
                    // handsfree only.
                    // TODO: Call hci_conn_enter_active_mode() from
                    // rfcomm_send_disc() in the kernel instead.
                    // See http://b/1716887
                    if (mHeadsetType == BluetoothHandsfree.TYPE_HANDSFREE) {
                        mHeadset.sendURC("+CIEV: 7,3");
                    }

                    if (mHeadset != null) {
                        mHeadset.disconnect();
                        mHeadset = null;
                    }
                    setState(BluetoothHeadset.STATE_DISCONNECTED,
                             BluetoothHeadset.RESULT_CANCELED,
                             BluetoothHeadset.LOCAL_DISCONNECT);
                    break;
                }
            }
        }
        public boolean startVoiceRecognition() {
            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
            synchronized (BluetoothHeadsetService.this) {
                if (mState != BluetoothHeadset.STATE_CONNECTED) {
                    return false;
                }
                return mBtHandsfree.startVoiceRecognition();
            }
        }
        public boolean stopVoiceRecognition() {
            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
            synchronized (BluetoothHeadsetService.this) {
                if (mState != BluetoothHeadset.STATE_CONNECTED) {
                    return false;
                }
                return mBtHandsfree.stopVoiceRecognition();
            }
        }
        public boolean setPriority(BluetoothDevice device, int priority) {
            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                           "Need BLUETOOTH_ADMIN permission");
            if (priority < BluetoothHeadset.PRIORITY_OFF) {
                return false;
            }
            mHeadsetPriority.set(device, priority);
            return true;
        }
        public int getPriority(BluetoothDevice device) {
            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

            return mHeadsetPriority.get(device);
        }
        public int getBatteryUsageHint() {
            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

            return HeadsetBase.getAtInputCount();
        }
    };

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (DBG) log("Stopping BluetoothHeadsetService");
        unregisterReceiver(mBluetoothReceiver);
        mBtHandsfree.onBluetoothDisabled();
        mAg.stop();
        sHasStarted = false;
        setState(BluetoothHeadset.STATE_DISCONNECTED,
                 BluetoothHeadset.RESULT_CANCELED,
                 BluetoothHeadset.LOCAL_DISCONNECT);
        mHeadsetType = BluetoothHandsfree.TYPE_UNKNOWN;
    }

    private class HeadsetPriority {
        private HashMap<BluetoothDevice, Integer> mPriority =
                new HashMap<BluetoothDevice, Integer>();

        public synchronized boolean load() {
            Set<BluetoothDevice> devices = mAdapter.getBondedDevices();
            if (devices == null) {
                return false;  // for example, bluetooth is off
            }
            for (BluetoothDevice device : devices) {
                load(device);
            }
            return true;
        }

        private synchronized int load(BluetoothDevice device) {
            int priority = Settings.Secure.getInt(getContentResolver(),
                    Settings.Secure.getBluetoothHeadsetPriorityKey(device.getAddress()),
                    BluetoothHeadset.PRIORITY_UNDEFINED);
            mPriority.put(device, new Integer(priority));
            if (DBG) log("Loaded priority " + device + " = " + priority);
            return priority;
        }

        public synchronized int get(BluetoothDevice device) {
            Integer priority = mPriority.get(device);
            if (priority == null) {
                return load(device);
            }
            return priority.intValue();
        }

        public synchronized void set(BluetoothDevice device, int priority) {
            int oldPriority = get(device);
            if (oldPriority == priority) {
                return;
            }
            mPriority.put(device, new Integer(priority));
            Settings.Secure.putInt(getContentResolver(),
                    Settings.Secure.getBluetoothHeadsetPriorityKey(device.getAddress()),
                    priority);
            if (DBG) log("Saved priority " + device + " = " + priority);
        }

        /** Mark this headset as highest priority */
        public synchronized void bump(BluetoothDevice device) {
            int oldPriority = get(device);
            int maxPriority = BluetoothHeadset.PRIORITY_AUTO_CONNECT;

            // Find max, not including given address
            for (BluetoothDevice d : mPriority.keySet()) {
                if (device.equals(d)) continue;
                int p = mPriority.get(d).intValue();
                if (p > maxPriority) {
                    maxPriority = p;
                }
            }
            if (maxPriority >= oldPriority) {
                int p = maxPriority + 1;
                set(device, p);
                if (p >= Integer.MAX_VALUE) {
                    rebalance();
                }
            }
        }

        /** shifts all non-zero priorities to be monotonically increasing from
         * PRIORITY_AUTO_CONNECT */
        private synchronized void rebalance() {
            LinkedList<BluetoothDevice> sorted = getSorted();
            if (DBG) log("Rebalancing " + sorted.size() + " headset priorities");

            ListIterator<BluetoothDevice> li = sorted.listIterator(sorted.size());
            int priority = BluetoothHeadset.PRIORITY_AUTO_CONNECT;
            while (li.hasPrevious()) {
                BluetoothDevice device = li.previous();
                set(device, priority);
                priority++;
            }
        }

        /** Get list of headsets sorted by decreasing priority.
         * Headsets with priority less than AUTO_CONNECT are not included */
        public synchronized LinkedList<BluetoothDevice> getSorted() {
            LinkedList<BluetoothDevice> sorted = new LinkedList<BluetoothDevice>();
            HashMap<BluetoothDevice, Integer> toSort =
                    new HashMap<BluetoothDevice, Integer>(mPriority);

            // add in sorted order. this could be more efficient.
            while (true) {
                BluetoothDevice maxDevice = null;
                int maxPriority = BluetoothHeadset.PRIORITY_AUTO_CONNECT;
                for (BluetoothDevice device : toSort.keySet()) {
                    int priority = toSort.get(device).intValue();
                    if (priority >= maxPriority) {
                        maxDevice = device;
                        maxPriority = priority;
                    }
                }
                if (maxDevice == null) {
                    break;
                }
                sorted.addLast(maxDevice);
                toSort.remove(maxDevice);
            }
            return sorted;
        }
    }

    /** If this property is false, then don't auto-reconnect BT headset */
    private static final String DEBUG_AUTO_RECONNECT = "debug.bt.hshfp.auto_reconnect";

    private boolean debugDontReconnect() {
        return (!SystemProperties.getBoolean(DEBUG_AUTO_RECONNECT, true));
    }

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