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(安卓)Auto-IP support
  2. android折叠展开自定义列表项测试
  3. android 多项对话框
  4. 【Android网络编程】获取网络图片,具有缓存功能
  5. Linux命令行安装配置Android(安卓)SDK
  6. android 中判断有无网络连接
  7. Android自定义对话框(Dialog)位置,大小
  8. DialogFragment设置自定义动画
  9. Android(安卓)循环读取名字相似的图片

随机推荐

  1. android:scrollbarStyle属性及滚动条和分
  2. Android(安卓)XML文件解析
  3. RK3326 Android(安卓)8.1 为自己的APK的
  4. Android(安卓)Studio在Gradle中隐藏Keyst
  5. Android中做一个无标题窗口
  6. Android笔记--handler机制
  7. Android定时器的使用,
  8. 创建 cocos2d-x+lua for android 步骤
  9. 用网络adb连接调试Android
  10. Android下使用Socket连接网络电脑