在android4.2中,Google更換了android的藍牙協議棧,從Bluez換成Bluedroid,我也是初涉這個方面,順便記錄一下。
http://source.android.com/devices/bluetooth.html
html
android development對於4.3藍牙的介紹:java
android提供BlueDroid做爲默認的協議棧,BlueDroid分爲兩個部分:android
一、Bluetooth Embedded System(BTE),它實現了BT的核心功能。app
二、Bluetooth Application Layer (BTA),用於和android framework層交互。this
BT 系統服務經過JNI與BT stack交互,而且經過Binder IPC通訊與應用交互。這個系統服務同時也提供給RD獲取不一樣的BT profiles;下面的圖標展現BT stack的一個大致的結構:code
1、application Frameworkhtm
這個層的代碼主要是利用android.bluetooth APIS 和 bluetooth hardware進行交互。 也就是經過Binder IPC機制調用bluetooth 進程;對象
代碼位於framework/base/core/java/android.bluetooth/下。繼承
好比A2DP的鏈接:framework/base/core/java/android.bluetooth/BluetoothA2dp.java中的connect(Bluetoothevice)方法。接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); return false; } |
經過Binder IPC 通訊機制,調用到packages/apps/Bluetooth/src/com.android.bluetooth.a2dp/A2dpService.java下一個內部私有類
A2dpService是一個繼承於ProfileService,而ProfileService是繼承於Service的。
private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub{}的connect(BluetoothDevice)方法。
1 2 3 4 5 |
public boolean connect(BluetoothDevice device) { A2dpService service = getService(); if (service == null) return false; return service.connect(device); } |
而後調用到A2dpService的connect(BluetoothDevice)方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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(A2dpStateMachine.CONNECT, device); return true; } |
這個過程就是Bluetooth Application Framework與Bluetooth Process的調用過程。
2、Bluetooth System service
Bluetooth System service位於packages/apps/Bluetooth下,它打包成一個android app包,而且在android framework 層實現BT service
和各類profile。BT app會經過JNI調用到HAL層。
A2dpService的connect方法會發送一個StateMachine.sendMessage(A2dpStateMachine.CONNECT, device)的message,這個message會被A2dpStateMachine對象的processMessage(Message)方法接收到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
case CONNECT: BluetoothDevice device = (BluetoothDevice) message.obj; broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); if (!connectA2dpNative(getByteAddress(device)) ) { broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); break; } synchronized (A2dpStateMachine.this) { mTargetDevice = device; transitionTo(mPending); } // TODO(BT) remove CONNECT_TIMEOUT when the stack // sends back events consistently sendMessageDelayed(CONNECT_TIMEOUT, 30000); break; |
最重要的一句:connectA2dpNative(getByteAddress(device);
即會經過JNI調用到Native;
private native boolean connectA2dpNative(byte[] address);
3、JNI
與android.bluetooth有關的JNI代碼位於packages/apps/bluetooth/jni下,JNI 的代碼會調用到HAL層,而且在確信一些BT操做被觸發時,會從HAL
獲取一些回調。好比當BT設備被發現時。
再回到A2dp鏈接的例子中來,BT System Service經過JNI會調用到com_android_bluetooth_a2dp.cpp中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) { jbyte *addr; bt_bdaddr_t * btAddr; bt_status_t status; ALOGI("%s: sBluetoothA2dpInterface: %p", __FUNCTION__, sBluetoothA2dpInterface); if (!sBluetoothA2dpInterface) return JNI_FALSE; addr = env->GetByteArrayElements(address, NULL); btAddr = (bt_bdaddr_t *) addr; if (!addr) { jniThrowIOException(env, EINVAL); return JNI_FALSE; } if ((status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { ALOGE("Failed HF connection, status: %d", status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } |
重點代碼是:status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr);
這個sBluetoothA2dpInterface結構體對象是在initNative(JNIEnv *env, jobject object)方法時獲得的。
1 2 3 4 5 |
if ( (sBluetoothA2dpInterface = (btav_interface_t *) btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) { ALOGE("Failed to get Bluetooth A2DP Interface"); return; } |
4、HAL
硬件抽象層定義android.bluetooth APIs和BT process調用的標準接口,而且你必須實現這些接口來讓你的BT hardware功能運行正常。BT HAL的
的頭文件位於hardware/libhardware/include/hardware/bluetooth.h和hardware/libhardware/include/hardware/bt_*.h 文件中。
JNI中sBluetoothA2dpInterface是一個btav_interface_t結構體,位於hardware/libhardware/include/hardware/bt_av.h中,定義爲:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
typedef struct { size_t size; bt_status_t (*init)( btav_callbacks_t* callbacks ); bt_status_t (*connect)( bt_bdaddr_t *bd_addr ); bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); void (*cleanup)( void ); } btav_interface_t; |
5、BT stack
做爲默認的BT stack,(4.2以前是bluez做爲協議棧的)
代碼位於external/bluetooth/bluedroid下,這個stack實現了通用的BT HAL而且也能夠經過擴展和改變配置來自定義。
A2dp的鏈接會調用到external/bluetooth/bluedroid/btif/src/btif_av.c的connect方法。
1 2 3 4 5 6 7 |
static bt_status_t connect(bt_bdaddr_t *bd_addr) { BTIF_TRACE_EVENT1("%s", __FUNCTION__); CHECK_BTAV_INIT(); return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int); } |
6、Vendor extension
爲了追蹤添加自定義拓展和一個HCI層,你能夠建立一個libbt-vendor模塊而且指定這些組件。