/*
 * 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.nfc.handover;

import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHidHost;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.OobData;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

import com.android.nfc.R;

/**
 * Connects / Disconnects from a Bluetooth headset (or any device that
 * might implement BT HSP, HFP, A2DP, or HOGP sink) when touched with NFC.
 *
 * This object is created on an NFC interaction, and determines what
 * sequence of Bluetooth actions to take, and executes them. It is not
 * designed to be re-used after the sequence has completed or timed out.
 * Subsequent NFC interactions should use new objects.
 *
 */
public class BluetoothPeripheralHandover implements BluetoothProfile.ServiceListener {
    static final String TAG = "BluetoothPeripheralHandover";
    static final boolean DBG = false;

    static final String ACTION_ALLOW_CONNECT = "com.android.nfc.handover.action.ALLOW_CONNECT";
    static final String ACTION_DENY_CONNECT = "com.android.nfc.handover.action.DENY_CONNECT";
    static final String ACTION_TIMEOUT_CONNECT = "com.android.nfc.handover.action.TIMEOUT_CONNECT";

    static final int TIMEOUT_MS = 20000;
    static final int RETRY_PAIRING_WAIT_TIME_MS = 2000;
    static final int RETRY_CONNECT_WAIT_TIME_MS = 5000;

    static final int STATE_INIT = 0;
    static final int STATE_WAITING_FOR_PROXIES = 1;
    static final int STATE_INIT_COMPLETE = 2;
    static final int STATE_WAITING_FOR_BOND_CONFIRMATION = 3;
    static final int STATE_BONDING = 4;
    static final int STATE_CONNECTING = 5;
    static final int STATE_DISCONNECTING = 6;
    static final int STATE_COMPLETE = 7;

    static final int RESULT_PENDING = 0;
    static final int RESULT_CONNECTED = 1;
    static final int RESULT_DISCONNECTED = 2;

    static final int ACTION_INIT = 0;
    static final int ACTION_DISCONNECT = 1;
    static final int ACTION_CONNECT = 2;

    static final int MSG_TIMEOUT = 1;
    static final int MSG_NEXT_STEP = 2;
    static final int MSG_RETRY = 3;

    static final int MAX_RETRY_COUNT = 3;

    final Context mContext;
    final BluetoothDevice mDevice;
    final String mName;
    final Callback mCallback;
    final BluetoothAdapter mBluetoothAdapter;
    final int mTransport;
    final boolean mProvisioning;

    final Object mLock = new Object();

    // only used on main thread
    int mAction;
    int mState;
    int mHfpResult;  // used only in STATE_CONNECTING and STATE_DISCONNETING
    int mA2dpResult; // used only in STATE_CONNECTING and STATE_DISCONNETING
    int mHidResult;
    int mRetryCount;
    OobData mOobData;
    boolean mIsHeadsetAvailable;
    boolean mIsA2dpAvailable;

    // protected by mLock
    BluetoothA2dp mA2dp;
    BluetoothHeadset mHeadset;
    BluetoothHidHost mInput;

    public interface Callback {
        public void onBluetoothPeripheralHandoverComplete(boolean connected);
    }

    public BluetoothPeripheralHandover(Context context, BluetoothDevice device, String name,
            int transport, OobData oobData, ParcelUuid[] uuids, BluetoothClass btClass,
            Callback callback) {
        checkMainThread();  // mHandler must get get constructed on Main Thread for toasts to work
        mContext = context;
        mDevice = device;
        mName = name;
        mTransport = transport;
        mOobData = oobData;
        mCallback = callback;
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        ContentResolver contentResolver = mContext.getContentResolver();
        mProvisioning = Settings.Secure.getInt(contentResolver,
                Settings.Global.DEVICE_PROVISIONED, 0) == 0;

        mIsHeadsetAvailable = hasHeadsetCapability(uuids, btClass);
        mIsA2dpAvailable = hasA2dpCapability(uuids, btClass);

        // Capability information is from NDEF optional field, then it might be empty.
        // If all capabilities indicate false, try to connect Headset and A2dp just in case.
        if (!mIsHeadsetAvailable && !mIsA2dpAvailable) {
            mIsHeadsetAvailable = true;
            mIsA2dpAvailable = true;
        }

        mState = STATE_INIT;
    }

    public boolean hasStarted() {
        return mState != STATE_INIT;
    }

    /**
     * Main entry point. This method is usually called after construction,
     * to begin the BT sequence. Must be called on Main thread.
     */
    public boolean start() {
        checkMainThread();
        if (mState != STATE_INIT || mBluetoothAdapter == null
                || (mProvisioning && mTransport != BluetoothDevice.TRANSPORT_LE)) {
            return false;
        }


        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
        filter.addAction(ACTION_ALLOW_CONNECT);
        filter.addAction(ACTION_DENY_CONNECT);

        mContext.registerReceiver(mReceiver, filter);

        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TIMEOUT), TIMEOUT_MS);

        mAction = ACTION_INIT;
        mRetryCount = 0;

        nextStep();

        return true;
    }

    /**
     * Called to execute next step in state machine
     */
    void nextStep() {
        if (mAction == ACTION_INIT) {
            nextStepInit();
        } else if (mAction == ACTION_CONNECT) {
            nextStepConnect();
        } else {
            nextStepDisconnect();
        }
    }

    /*
     * Enables bluetooth and gets the profile proxies
     */
    void nextStepInit() {
        switch (mState) {
            case STATE_INIT:
                if (mA2dp == null || mHeadset == null || mInput == null) {
                    mState = STATE_WAITING_FOR_PROXIES;
                    if (!getProfileProxys()) {
                        complete(false);
                    }
                    break;
                }
                // fall-through
            case STATE_WAITING_FOR_PROXIES:
                mState = STATE_INIT_COMPLETE;
                // Check connected devices and see if we need to disconnect
                synchronized(mLock) {
                    if (mTransport == BluetoothDevice.TRANSPORT_LE) {
                        if (mInput.getConnectedDevices().contains(mDevice)) {
                            Log.i(TAG, "ACTION_DISCONNECT addr=" + mDevice + " name=" + mName);
                            mAction = ACTION_DISCONNECT;
                        } else {
                            Log.i(TAG, "ACTION_CONNECT addr=" + mDevice + " name=" + mName);
                            mAction = ACTION_CONNECT;
                        }
                    } else {
                        if (mA2dp.getConnectedDevices().contains(mDevice) ||
                                mHeadset.getConnectedDevices().contains(mDevice)) {
                            Log.i(TAG, "ACTION_DISCONNECT addr=" + mDevice + " name=" + mName);
                            mAction = ACTION_DISCONNECT;
                        } else {
                            // Check if each profile of the device is disabled or not
                            if (mHeadset.getPriority(mDevice) == BluetoothProfile.PRIORITY_OFF) {
                                mIsHeadsetAvailable = false;
                            }
                            if (mA2dp.getPriority(mDevice) == BluetoothProfile.PRIORITY_OFF) {
                                mIsA2dpAvailable = false;
                            }
                            if (!mIsHeadsetAvailable && !mIsA2dpAvailable) {
                                Log.i(TAG, "Both Headset and A2DP profiles are unavailable");
                                complete(false);
                                break;
                            }
                            Log.i(TAG, "ACTION_CONNECT addr=" + mDevice + " name=" + mName);
                            mAction = ACTION_CONNECT;
                        }
                    }
                }
                nextStep();
        }

    }

    void nextStepDisconnect() {
        switch (mState) {
            case STATE_INIT_COMPLETE:
                mState = STATE_DISCONNECTING;
                synchronized (mLock) {
                    if (mTransport == BluetoothDevice.TRANSPORT_LE) {
                        if (mInput.getConnectionState(mDevice)
                                != BluetoothProfile.STATE_DISCONNECTED) {
                            mHidResult = RESULT_PENDING;
                            mInput.disconnect(mDevice);
                            toast(getToastString(R.string.disconnecting_peripheral));
                            break;
                        } else {
                            mHidResult = RESULT_DISCONNECTED;
                        }
                    } else {
                        if (mHeadset.getConnectionState(mDevice)
                                != BluetoothProfile.STATE_DISCONNECTED) {
                            mHfpResult = RESULT_PENDING;
                            mHeadset.disconnect(mDevice);
                        } else {
                            mHfpResult = RESULT_DISCONNECTED;
                        }
                        if (mA2dp.getConnectionState(mDevice)
                                != BluetoothProfile.STATE_DISCONNECTED) {
                            mA2dpResult = RESULT_PENDING;
                            mA2dp.disconnect(mDevice);
                        } else {
                            mA2dpResult = RESULT_DISCONNECTED;
                        }
                        if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
                            toast(getToastString(R.string.disconnecting_peripheral));
                            break;
                        }
                    }
                }
                // fall-through
            case STATE_DISCONNECTING:
                if (mTransport == BluetoothDevice.TRANSPORT_LE) {
                    if (mHidResult == RESULT_DISCONNECTED) {
                        toast(getToastString(R.string.disconnected_peripheral));
                        complete(false);
                    }

                    break;
                } else {
                    if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
                        // still disconnecting
                        break;
                    }
                    if (mA2dpResult == RESULT_DISCONNECTED && mHfpResult == RESULT_DISCONNECTED) {
                        toast(getToastString(R.string.disconnected_peripheral));
                    }
                    complete(false);
                    break;
                }

        }

    }

    private String getToastString(int resid) {
        return mContext.getString(resid, mName != null ? mName : R.string.device);
    }

    boolean getProfileProxys() {

        if (mTransport == BluetoothDevice.TRANSPORT_LE) {
            if (!mBluetoothAdapter.getProfileProxy(mContext, this, BluetoothProfile.HID_HOST))
                return false;
        } else {
            if(!mBluetoothAdapter.getProfileProxy(mContext, this, BluetoothProfile.HEADSET))
                return false;

            if(!mBluetoothAdapter.getProfileProxy(mContext, this, BluetoothProfile.A2DP))
                return false;
        }

        return true;
    }

    void nextStepConnect() {
        switch (mState) {
            case STATE_INIT_COMPLETE:

                if (mDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
                    requestPairConfirmation();
                    mState = STATE_WAITING_FOR_BOND_CONFIRMATION;
                    break;
                }

                if (mTransport == BluetoothDevice.TRANSPORT_LE) {
                    if (mDevice.getBondState() != BluetoothDevice.BOND_NONE) {
                        mDevice.removeBond();
                        requestPairConfirmation();
                        mState = STATE_WAITING_FOR_BOND_CONFIRMATION;
                        break;
                    }
                }
                // fall-through
            case STATE_WAITING_FOR_BOND_CONFIRMATION:
                if (mDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
                    startBonding();
                    break;
                }
                // fall-through
            case STATE_BONDING:
                // Bluetooth Profile service will correctly serialize
                // HFP then A2DP connect
                mState = STATE_CONNECTING;
                synchronized (mLock) {
                    if (mTransport == BluetoothDevice.TRANSPORT_LE) {
                        if (mInput.getConnectionState(mDevice)
                                != BluetoothProfile.STATE_CONNECTED) {
                            mHidResult = RESULT_PENDING;
                            toast(getToastString(R.string.connecting_peripheral));
                            break;
                        } else {
                            mHidResult = RESULT_CONNECTED;
                        }
                    } else {
                        if (mHeadset.getConnectionState(mDevice) !=
                                BluetoothProfile.STATE_CONNECTED) {
                            if (mIsHeadsetAvailable) {
                                mHfpResult = RESULT_PENDING;
                                mHeadset.connect(mDevice);
                            } else {
                                mHfpResult = RESULT_DISCONNECTED;
                            }
                        } else {
                            mHfpResult = RESULT_CONNECTED;
                        }
                        if (mA2dp.getConnectionState(mDevice) != BluetoothProfile.STATE_CONNECTED) {
                            if (mIsA2dpAvailable) {
                                mA2dpResult = RESULT_PENDING;
                                mA2dp.connect(mDevice);
                            } else {
                                mA2dpResult = RESULT_DISCONNECTED;
                            }
                        } else {
                            mA2dpResult = RESULT_CONNECTED;
                        }
                        if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
                            if (mRetryCount == 0) {
                                toast(getToastString(R.string.connecting_peripheral));
                            }
                            if (mRetryCount < MAX_RETRY_COUNT) {
                                sendRetryMessage(RETRY_CONNECT_WAIT_TIME_MS);
                                break;
                            }
                        }
                    }
                }
                // fall-through
            case STATE_CONNECTING:
                if (mTransport == BluetoothDevice.TRANSPORT_LE) {
                    if (mHidResult == RESULT_PENDING) {
                        break;
                    } else if (mHidResult == RESULT_CONNECTED) {
                        toast(getToastString(R.string.connected_peripheral));
                        mDevice.setAlias(mName);
                        complete(true);
                    } else {
                        toast (getToastString(R.string.connect_peripheral_failed));
                        complete(false);
                    }
                } else {
                    if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
                        // another connection type still pending
                        break;
                    }
                    if (mA2dpResult == RESULT_CONNECTED || mHfpResult == RESULT_CONNECTED) {
                        // we'll take either as success
                        toast(getToastString(R.string.connected_peripheral));
                        if (mA2dpResult == RESULT_CONNECTED) startTheMusic();
                        mDevice.setAlias(mName);
                        complete(true);
                    } else {
                        toast (getToastString(R.string.connect_peripheral_failed));
                        complete(false);
                    }
                }
                break;
        }
    }

    void startBonding() {
        mState = STATE_BONDING;
        if (mRetryCount == 0) {
            toast(getToastString(R.string.pairing_peripheral));
        }
        if (mOobData != null) {
            if (!mDevice.createBondOutOfBand(mTransport, mOobData)) {
                toast(getToastString(R.string.pairing_peripheral_failed));
                complete(false);
            }
        } else if (!mDevice.createBond(mTransport)) {
                toast(getToastString(R.string.pairing_peripheral_failed));
                complete(false);
        }
    }

    void handleIntent(Intent intent) {
        String action = intent.getAction();
        // Everything requires the device to match...
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        if (!mDevice.equals(device)) return;

        if (ACTION_ALLOW_CONNECT.equals(action)) {
            mHandler.removeMessages(MSG_TIMEOUT);
            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TIMEOUT), TIMEOUT_MS);
            nextStepConnect();
        } else if (ACTION_DENY_CONNECT.equals(action)) {
            complete(false);
        } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)
                && mState == STATE_BONDING) {
            int bond = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                    BluetoothAdapter.ERROR);
            if (bond == BluetoothDevice.BOND_BONDED) {
                mRetryCount = 0;
                nextStepConnect();
            } else if (bond == BluetoothDevice.BOND_NONE) {
                if (mRetryCount < MAX_RETRY_COUNT) {
                    sendRetryMessage(RETRY_PAIRING_WAIT_TIME_MS);
                } else {
                    toast(getToastString(R.string.pairing_peripheral_failed));
                    complete(false);
                }
            }
        } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(action) &&
                (mState == STATE_CONNECTING || mState == STATE_DISCONNECTING)) {
            int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR);
            if (state == BluetoothProfile.STATE_CONNECTED) {
                mHfpResult = RESULT_CONNECTED;
                nextStep();
            } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
                if (mAction == ACTION_CONNECT && mRetryCount < MAX_RETRY_COUNT) {
                    sendRetryMessage(RETRY_CONNECT_WAIT_TIME_MS);
                } else {
                    mHfpResult = RESULT_DISCONNECTED;
                    nextStep();
                }
            }
        } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action) &&
                (mState == STATE_CONNECTING || mState == STATE_DISCONNECTING)) {
            int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR);
            if (state == BluetoothProfile.STATE_CONNECTED) {
                mA2dpResult = RESULT_CONNECTED;
                nextStep();
            } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
                if (mAction == ACTION_CONNECT && mRetryCount < MAX_RETRY_COUNT) {
                    sendRetryMessage(RETRY_CONNECT_WAIT_TIME_MS);
                } else {
                    mA2dpResult = RESULT_DISCONNECTED;
                    nextStep();
                }
            }
        } else if (BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED.equals(action) &&
                (mState == STATE_CONNECTING || mState == STATE_DISCONNECTING)) {
            int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR);
            if (state == BluetoothProfile.STATE_CONNECTED) {
                mHidResult = RESULT_CONNECTED;
                nextStep();
            } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
                mHidResult = RESULT_DISCONNECTED;
                nextStep();
            }
        }
    }

    void complete(boolean connected) {
        if (DBG) Log.d(TAG, "complete()");
        mState = STATE_COMPLETE;
        mContext.unregisterReceiver(mReceiver);
        mHandler.removeMessages(MSG_TIMEOUT);
        mHandler.removeMessages(MSG_RETRY);
        synchronized (mLock) {
            if (mA2dp != null) {
                mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mA2dp);
            }
            if (mHeadset != null) {
                mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadset);
            }

            if (mInput != null) {
                mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HID_HOST, mInput);
            }

            mA2dp = null;
            mHeadset = null;
            mInput = null;
        }
        mCallback.onBluetoothPeripheralHandoverComplete(connected);
    }

    void toast(CharSequence text) {
        Toast.makeText(mContext,  text, Toast.LENGTH_SHORT).show();
    }

    void startTheMusic() {
        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
        if (helper != null) {
            KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY);
            helper.sendMediaButtonEvent(keyEvent, false);
            keyEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY);
            helper.sendMediaButtonEvent(keyEvent, false);
        } else {
            Log.w(TAG, "Unable to send media key event");
        }
    }

    void requestPairConfirmation() {
        Intent dialogIntent = new Intent(mContext, ConfirmConnectActivity.class);
        dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        dialogIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
        dialogIntent.putExtra(BluetoothDevice.EXTRA_NAME, mName);

        mContext.startActivity(dialogIntent);
    }

    boolean hasA2dpCapability(ParcelUuid[] uuids, BluetoothClass btClass) {
        if (uuids != null) {
            for (ParcelUuid uuid : uuids) {
                if (BluetoothUuid.isAudioSink(uuid) || BluetoothUuid.isAdvAudioDist(uuid)) {
                    return true;
                }
            }
        }
        if (btClass != null && btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
            return true;
        }
        return false;
    }

    boolean hasHeadsetCapability(ParcelUuid[] uuids, BluetoothClass btClass) {
        if (uuids != null) {
            for (ParcelUuid uuid : uuids) {
                if (BluetoothUuid.isHandsfree(uuid) || BluetoothUuid.isHeadset(uuid)) {
                    return true;
                }
            }
        }
        if (btClass != null && btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
            return true;
        }
        return false;
    }

    final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_TIMEOUT:
                    if (mState == STATE_COMPLETE) return;
                    Log.i(TAG, "Timeout completing BT handover");
                    if (mState == STATE_WAITING_FOR_BOND_CONFIRMATION) {
                        mContext.sendBroadcast(new Intent(ACTION_TIMEOUT_CONNECT));
                    } else if (mState == STATE_BONDING) {
                        toast(getToastString(R.string.pairing_peripheral_failed));
                    } else if (mState == STATE_CONNECTING) {
                        if (mHidResult == RESULT_PENDING) {
                            mHidResult = RESULT_DISCONNECTED;
                        }
                        if (mA2dpResult == RESULT_PENDING) {
                            mA2dpResult = RESULT_DISCONNECTED;
                        }
                        if (mHfpResult == RESULT_PENDING) {
                            mHfpResult = RESULT_DISCONNECTED;
                        }
                        // Check if any one profile is connected, then it takes as success
                        nextStepConnect();
                        break;
                    }
                    complete(false);
                    break;
                case MSG_NEXT_STEP:
                    nextStep();
                    break;
                case MSG_RETRY:
                    mHandler.removeMessages(MSG_RETRY);
                    if (mState == STATE_BONDING) {
                        mState = STATE_WAITING_FOR_BOND_CONFIRMATION;
                    } else if (mState == STATE_CONNECTING) {
                        mState = STATE_BONDING;
                    }
                    mRetryCount++;
                    nextStepConnect();
                    break;
            }
        }
    };

    final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            handleIntent(intent);
        }
    };

    static void checkMainThread() {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw new IllegalThreadStateException("must be called on main thread");
        }
    }

    @Override
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
        synchronized (mLock) {
            switch (profile) {
                case BluetoothProfile.HEADSET:
                    mHeadset = (BluetoothHeadset) proxy;
                    if (mA2dp != null) {
                        mHandler.sendEmptyMessage(MSG_NEXT_STEP);
                    }
                    break;
                case BluetoothProfile.A2DP:
                    mA2dp = (BluetoothA2dp) proxy;
                    if (mHeadset != null) {
                        mHandler.sendEmptyMessage(MSG_NEXT_STEP);
                    }
                    break;
                case BluetoothProfile.HID_HOST:
                    mInput = (BluetoothHidHost) proxy;
                    if (mInput != null) {
                        mHandler.sendEmptyMessage(MSG_NEXT_STEP);
                    }
                    break;
            }
        }
    }

    @Override
    public void onServiceDisconnected(int profile) {
        // We can ignore these
    }

    void sendRetryMessage(int waitTime) {
        if (!mHandler.hasMessages(MSG_RETRY)) {
            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RETRY), waitTime);
        }
    }
}
