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