Android HFP Profile 连接过程

packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDevicePreference.java

    void onClicked() {
        int bondState = mCachedDevice.getBondState();

        if (mCachedDevice.isConnected()) {
            askDisconnect();
        } else if (bondState == BluetoothDevice.BOND_BONDED) { //已经配对,但是未连接
            <span style="margin: 0px; padding: 0px; border: 0px; color: rgb(255, 0, 0); background: transparent;">mCachedDevice.connect(true);</span>
        } else if (bondState == BluetoothDevice.BOND_NONE) { //没有配对
            <span style="margin: 0px; padding: 0px; border: 0px; color: rgb(255, 0, 0); background: transparent;">pair();</span>
        }
    }
	

mCachedDevice.connect(true);方法会直接调用CachedBluetoothDevice.java的connect的方法。

packages/apps/Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java

   void connect(boolean connectAllProfiles) {
        if (!ensurePaired()) {  //配对处理暂时不关注
            return;
        }
        mConnectAttempted = SystemClock.elapsedRealtime();
        connectWithoutResettingTimer(connectAllProfiles);
    }

代码执行到connectWithoutResettingTimer,注释就不粘贴了。 

    private void connectWithoutResettingTimer(boolean connectAllProfiles) {
         ......
        // Reset the only-show-one-error-dialog tracking variable
        mIsConnectingErrorPossible = true;
        int preferredProfiles = 0;
        for (LocalBluetoothProfile profile : mProfiles) {
            if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
                if (profile.isPreferred(mDevice)) {
                    ++preferredProfiles;
                    connectInt(profile);
                }
            }
        }
        if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles);

        if (preferredProfiles == 0) {
            connectAutoConnectableProfiles();
        }
    }

不同的协议实现类,继承于LocalBluetoothProfile,以HeadsetProfile为例。

    synchronized void connectInt(LocalBluetoothProfile profile) {
        if (!ensurePaired()) {
            return;
        }
        if (<span style="margin: 0px; padding: 0px; border: 0px; color: rgb(255, 0, 0); background: transparent;">profile.connect(mDevice)</span>) {
            if (Utils.D) {
                Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile));
            }
            return;
        }
        Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName);
    }

这个方法中,profile.connnect(),直接调用 HeadsetProfile的connnect(),其实headset/handsfree 是共用同一个service。

packages/apps/Settings/src/com/android/settings/bluetooth/HeadsetProfile.java

    public boolean connect(BluetoothDevice device) {
        if (mService == null) return false;
        List<BluetoothDevice> sinks = mService.getConnectedDevices();
        if (sinks != null) {//断开所有连接
            for (BluetoothDevice sink : sinks) {
                mService.disconnect(sink);
            }
        }
        return mService.connect(device);
    }

mService.connect 直接进入framwork层,调用Bluetooth Headset server的api。

frameworks/base/core/java/android/bluetooth/BluetoothHeadset.java

    public boolean connect(BluetoothDevice device) {
        if (DBG) log("connect(" + device + ")");
        if (mService != null && isEnabled() &&
            isValidDevice(device)) {
            try {
                return mService.connect(device);
            } catch (RemoteException e) {
                Log.e(TAG, Log.getStackTraceString(new Throwable()));
                return false;
            }
        }
        if (mService == null) Log.w(TAG, "Proxy not attached to service");
        return false;
    }

framework 中转了一下,利用Binder机制再次进入Bluetooth模块。

frameworks/base/core/java/android/bluetooth/IBluetoothHeadset.aidl,实现类是

packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetService.java
注意顺序:Setting->framewrok->Bluetooth

        public boolean connect(BluetoothDevice device) {
            HeadsetService service = getService();
            if (service == null) return false;
            return service.connect(device);
        }

IBluetoothHeadset.Sub仅仅是一个连接,什么都不做直接进入HeadsetService.java的connect 方法。

    public boolean connect(BluetoothDevice device) {       
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                       "Need BLUETOOTH ADMIN permission");

        if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
            return false;
        }
        int connectionState = mStateMachine.getConnectionState(device);
        if (connectionState == BluetoothProfile.STATE_CONNECTED ||
            connectionState == BluetoothProfile.STATE_CONNECTING) {
            return false;
        }
        mStateMachine.sendMessage(HeadsetStateMachine.CONNECT, device);//万恶的状态机开始工作
        return true;
    }

packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java

记住当前为 未连接状态,所以应该进入 Disconnected的状态,Disconnected的processMessage方法中:

            switch(message.what) {
                case CONNECT:
                    BluetoothDevice device = (BluetoothDevice) message.obj;
                    broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING,
                                   BluetoothProfile.STATE_DISCONNECTED);

                    if (!<span style="margin: 0px; padding: 0px; border: 0px; color: rgb(255, 0, 0); background: transparent;">connectHfpNative(getByteAddress(device)) </span>) {
                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED,
                                       BluetoothProfile.STATE_CONNECTING);
                        break;
                    }

                    synchronized (HeadsetStateMachine.this) {
                        mTargetDevice = device;
                        transitionTo(mPending);
                    }

connectHfpNative 连接,jni 方法 简单了。

packages\apps\bluetooth\jni\Com_android_bluetooth_hfp.cpp

    {"connectHfpNative", "([B)Z", (void *) connectHfpNative},
    static jboolean connectHfpNative(JNIEnv *env, jobject object, jbyteArray address) {
    jbyte *addr;
    bt_status_t status;

    ALOGI("%s: sBluetoothHfpInterface: %p", __FUNCTION__, sBluetoothHfpInterface);
    if (!sBluetoothHfpInterface) return JNI_FALSE;

    addr = env->GetByteArrayElements(address, NULL);
    if (!addr) {
        jniThrowIOException(env, EINVAL);
        return JNI_FALSE;
    }

    <span style="margin: 0px; padding: 0px; border: 0px; color: rgb(255, 0, 0); background: transparent;">if ((status = sBluetoothHfpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {</span>
        ALOGE("Failed HF connection, status: %d", status);
    }
    env->ReleaseByteArrayElements(address, addr, 0);
    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

关键函数是sBluetoothHfpInterface->connect((bt_bdaddr_t *)addr), connect定义在 hardware/libhardware/include/hardware/bt_hf.h,

但是实现却在:external/bluetooth/bluedroid/btif/src/btif_hf.c 中实现

#include <hardware/bt_hf.h>
static bt_status_t connect( bt_bdaddr_t *bd_addr )
{
    CHECK_BTHF_INIT();
    return btif_queue_connect(UUID_SERVCLASS_AG_HANDSFREE, bd_addr, connect_int);
}

看定义,直接连接handsfree

#define UUID_SERVCLASS_AG_HANDSFREE             0X111F  /* Handsfree profile */

btif_queue_connect的定义在下面文件中定义

external/bluetooth/bluedroid/btif/src/btif_profile_queue.c

进入bt_status_t btif_queue_connect看定义:

</pre><pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 10px; font-size: 13px; line-height: 24.05px; background-color: rgb(255, 255, 255);">bt_status_t btif_queue_connect(uint16_t uuid, const bt_bdaddr_t *bda,
                        btif_connect_cb_t *connect_cb)
{
    connect_node_t node;
    memset(&node, 0, sizeof(connect_node_t));
    memcpy(&(node.bda), bda, sizeof(bt_bdaddr_t));
    node.uuid = uuid;
    node.p_cb = connect_cb;

    return btif_transfer_context(queue_int_handle_evt, BTIF_QUEUE_CONNECT_EVT,
                          (char*)&node, sizeof(connect_node_t), NULL);
}

btif_transfer_context定义在如下文件中

external/bluetooth/bluedroid/btif/src/btif_core.c

btif_transfer_context内容就不粘贴了,里面发送消息,调用

external/bluetooth/bluedroid/gki/common/gki_buffer.c

void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg)

GKI_send_msg发送一条GKI信息到BTA,GKI_send_msg有三个参数,第一个参数是线程id,也作为task id, 通过bta_sys_init获得,第二个参数是mailbox id,第三个是上一步封装好的p_msg

GKI_send_msg首先对p_msg进一步封装成event,通过链表存到mailbox id对应的任务队列中,调用external/bluetooth/bluedroid/gki/ulinux/gki_ulinux.c :: GKI_send_event
进行发送。
GKI_send_event设置事件掩码
gki_cb.com.OSWaitEvt[task_id] |= event;, 
通过pthread_cond_signal(&gki_cb.os.thread_evt_cond[task_id]);通知另外线程。
这样,在另外一个等待线程函数中gki_ulinux.c :: GKI_wait可以返回了。

你可能感兴趣的:(Android HFP Profile 连接过程)