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可以返回了。

更多相关文章

  1. Android 实现监听事件的几种方法
  2. Android View的构造方法
  3. Android中重写onBackPressed()方法实现双击退出
  4. Android简单实现更换桌面背景的方法
  5. android折叠展开自定义列表项测试
  6. 自定义Tab选项卡
  7. android绘制view的过程(自定义view一)
  8. android 三种解析,构建xml方法

随机推荐

  1. Android:漫画APP开发笔记之ListView中图
  2. 【Android(安卓)系统开发】 编译 Android
  3. PhoneGap Android环境搭建
  4. android jni 程序框架搭建
  5. Android(安卓)Fastboot
  6. 2010.11.28(2)———android 展示网页 和
  7. 什么是Android-Android中文SDK
  8. UI组件之AdapterView及其子类(二)GridView
  9. windows下载android源代码
  10. Android的常用adb命令