一、蓝牙总体架构
二、代码分布
1.应用
/packages/apps/Settings(原生的设置应用)
/packages/apps/Bluetooth(原生的蓝牙应用)
2.蓝牙java框架
/frameworks/base/core/java/android/bluetooth(蓝牙部分对应的应用程序api)
/frameworks/base/services/java/com/android/server/BluetoothManagerService.java(蓝牙相关的系统服务)
3.Bluedroid库
/external/bluetooth
4.适配层
/system/bluetooth
5.JNI部分
未知
6.蓝牙驱动
/driver/bluetooth
/driver/usb
/driver/serial
三、蓝牙各模块框架类图与设计模式
四、蓝牙启动过程
1.看下蓝牙框架层是怎么调用到BluetoothManagerService中去的
//SystemServer.java (frameworks\base\services\java\com\android\server)
如果采用的是模拟器内核,那么就不启动蓝牙服务,模拟器上不支持蓝牙
2.从BluetoothAdapter来看下应用是怎么调用蓝牙服务的
//BluetoothAdapter.java (\frameworks\base\core\java\android\bluetooth)
上面的mManagerService是在构造函数中传进来的,我们看下mManagerService的本质是什么:
//BluetoothAdapter.java
IBluetoothManager是一个接口,所以实际上mManagerService是BluetoothManagerService的一个Proxy
其中class BluetoothManagerService extends IBluetoothManager.Stub {
为什么呢?我们从BluetoothAdapter在应用中的使用能够看出来:
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
public static synchronized BluetoothAdapter getDefaultAdapter() {
可以知道BluetoothAdapter(IBluetoothManager managerService)中的参数就是上面的
ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
所以最后调用的是BluetoothManagerService.enable();
3.
public boolean enable() {
同样,BluetoothAdapter封装的一些接口最终都是调用到了BluetoothManagerSevice的函数实现。
五、应用层对框架层的调用
经过上面的一个垂直调用,我们再水平看下蓝牙框架层中的东西,打开/framework/base/core/java/android/bluetooth的源码,我们会发现其中都是一些java文件和aidl文件。
并且我们可以在编译代码后发现out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/bluetooth
这个目录下有一系列的接口文件生成。
我们用类图来描述框架层中的东西:
在了解蓝牙框架的时候,我们先了解下应用对框架类的使用:
packages\apps\Settings
Settings这个应用中最后会调用到CachedBluetoothDevice.connectInt
这个connect函数是有返回值得boolean型
profile.connect(mDevice))会调用到:
//BluetoothA2dp.java
这个问题是什么东西
这里的mService打印出来的结果是:
D/BluetoothA2dp( 1086):mService=android.bluetooth.IBluetoothA2dp$Stub$Proxy@41ce2f20
结合:mService = IBluetoothA2dp.Stub.asInterface(service);
我们可以在/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/bluetooth/IBluetoothA2dp.java中找到IBluetoothA2dp.Stub.asInterface();这个函数:
public static android.bluetooth.IBluetoothA2dp asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.bluetooth.IBluetoothA2dp))) {
return ((android.bluetooth.IBluetoothA2dp)iin);
}
return new android.bluetooth.IBluetoothA2dp.Stub.Proxy(obj);
}
这里返回的是service的一个实例
所以这个android.bluetooth.IBluetoothA2dp.Stub.Proxy(obj).connect()函数是:
A2dpService.connect()
//A2dpService.java
然后是:mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
因为final class A2dpStateMachine extends StateMachine ,sendMessage这个函数在StateMachine里面:
应该就是向设备发送了一个A2dpStateMachine.CONNECT消息。
然后由A2dpStateMachine相应状态的processMessage函数来处理,这里要是当前状态是Disconnected,则由此状态的processMessage来处理这个connect消息:
D/A2dpService( 1130): duanliang,connect begin
D/A2dpStateMachine( 1130): Disconnected process message: 1
//A2dpStateMachine.java
//A2dpStateMachine.java
现在我们关注一下connectA2dpNative(getByteAddress(device)) ,这就通过jni调用到了native层
六、框架层对Native层的调用
框架层会通过jni调用本地方法到达Native层
//A2dpStateMachine.java
Install: out/target/product/nt72668_tcl/system/lib/libbluetooth_jni.so
//com_android_bluetooth_a2dp.cpp
static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {
}
这里会调用到:
I/BluetoothA2dpServiceJni( 1130): Attempting to connect a2dp source
然后调用到:
I/bt-btif ( 1130): connect
I/bt-btif ( 1130): connect
我们仔细分析下其中的:
这个sBluetoothA2dpInterface结构体对象是在initNative(JNIEnv *env, jobjectobject)方法时得到的。
在/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp中实现的是bluetooth的JNI代码,是上层Java与下层Bluedroid的接口
先看下结构体类型:
static const btav_interface_t
再看下initNative:
其中btInf = getBluetoothInterface()
//com_android_bluetooth_btservice_AdapterService.cpp
const bt_interface_t* getBluetoothInterface() {
}
在
com_android_bluetooth_btservice_AdapterService.classInitNative中我们可以看到:
这里是获取一个蓝牙硬件抽象层的接口,就到达了硬件抽象层
七、Native层到HAL层(硬件抽象层)的调用
现在我们分析下蓝牙的硬件抽象层:
//Bluetooth.h
typedef struct {
} bluetooth_device_t;
typedef bluetooth_device_t bluetooth_module_t;
可以看到继承了hw_device_t定义了硬件模块结构体结构体bluetooth_device_t;
此外还有硬件接口结构体:bt_interface_t
还可以找到抽象层硬件模块ID
#define BT_HARDWARE_MODULE_ID "bluetooth"
#define BT_STACK_MODULE_ID "bluetooth"
#define BT_STACK_TEST_MODULE_ID "bluetooth_test"
这样,Android硬件抽象层规范的要求的模块ID、模块结构体以及硬件接口结构体都具备了。
然后我们可以到
但是我们找不到Bluetooth.c这个实现文件,这是因为,硬件抽象层的实现是第三方实现的,并且封装成了so库提供给我们,/system/lib/hw下的bluetooth.default.so就是第三方给我们提供的蓝牙硬件抽象层的库,从名字可以判断下面两个是蓝牙耳机和音箱对应的硬件抽象层库:
audio.btmic.default.so
audio.a2dp.default.so
八、硬件抽象层到内核驱动层
--------------------------------------------------------------------------------------------------------------
以上是以蓝牙音箱的连接过程作为主线,现在看下蓝牙游戏手柄的连接
这里走的是hid设备
九、蓝牙手柄
在中我们知道会调用到profile.connect(mDevice));
因为蓝牙手柄时Hid设备,所以会调用到:
//HidProfile.java
public boolean connect(BluetoothDevice device) {
Log.d(TAG,"duanliang,connect begin");
if (mService == null) return false;
return mService.connect(device);
}
然后调用到:
public boolean connect(BluetoothDevice device) {
Log.d(TAG,"duanliang,conect begin");
if (DBG) log("connect(" + device + ")");
if (mService != null && isEnabled() && isValidDevice(device)) {
try {
Log.d(TAG,"duanliang, before mService.connect(device);");
Log.d(TAG,"duanliang,mService ="+mService);
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;
}
然后调用到HidService.java(不同于蓝牙音箱,上面蓝牙音箱的mService.connect(device)调用到的是A2dpService)
boolean connect(BluetoothDevice device) {
Log.d(TAG,"duanliang,connect begin");
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (getConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED) {
Log.e(TAG, "Hid Device not disconnected: " + device);
return false;
}
if (getPriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
Log.e(TAG, "Hid Device PRIORITY_OFF: " + device);
return false;
}
Message msg = mHandler.obtainMessage(MESSAGE_CONNECT, device);
mHandler.sendMessage(msg);
return true;
}
然后由HidService中的handle处理消息:
case MESSAGE_CONNECT:
{
BluetoothDevice device = (BluetoothDevice) msg.obj;
if (!connectHidNative(Utils.getByteAddress(device)) ) {
broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING);
broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED);
break;
}
mTargetDevice = device;
}
break;
注意,这里还有一个mTargetDevice,应该是在连接之后需要使用的一个变量。这儿Native函数有一个返回值,所以应该是连接结果通过这个返回值来标识。
这里调用到Native层:
connectHidNative
//Com_android_bluetooth_hid.cpp
static jboolean connectHidNative(JNIEnv *env, jobject object, jbyteArray address) {
bt_status_t status;
jbyte *addr;
jboolean ret = JNI_TRUE;
if (!sBluetoothHidInterface) return JNI_FALSE;
addr = env->GetByteArrayElements(address, NULL);
if (!addr) {
ALOGE("Bluetooth device address null");
return JNI_FALSE;
}
if ((status = sBluetoothHidInterface->connect((bt_bdaddr_t *) addr)) !=
BT_STATUS_SUCCESS) {
ALOGE("Failed HID channel connection, status: %d", status);
ret = JNI_FALSE;
}
env->ReleaseByteArrayElements(address, addr, 0);
return ret;
}
这里调用status = sBluetoothHidInterface->connect((bt_bdaddr_t *) addr))进行连接,
而这个sBluetoothHidInterface
static const bthh_interface_t *sBluetoothHidInterface = NULL;也是在initializeNative函数中初始化的
//Com_android_bluetooth_hid.cpp
static void initializeNative(JNIEnv *env, jobject object) {
const bt_interface_t* btInf;
bt_status_t status;
if ( (btInf = getBluetoothInterface()) == NULL) {
ALOGE("Bluetooth module is not loaded");
return;
}
if (sBluetoothHidInterface !=NULL) {
ALOGW("Cleaning up Bluetooth HID Interface before initializing...");
sBluetoothHidInterface->cleanup();
sBluetoothHidInterface = NULL;
}
if (mCallbacksObj != NULL) {
ALOGW("Cleaning up Bluetooth GID callback object");
env->DeleteGlobalRef(mCallbacksObj);
mCallbacksObj = NULL;
}
if ( (sBluetoothHidInterface = (bthh_interface_t *)
btInf->get_profile_interface(BT_PROFILE_HIDHOST_ID)) == NULL) {
ALOGE("Failed to get Bluetooth HID Interface");
return;
}
if ( (status = sBluetoothHidInterface->init(&sBluetoothHidCallbacks)) != BT_STATUS_SUCCESS) {
ALOGE("Failed to initialize Bluetooth HID, status: %d", status);
sBluetoothHidInterface = NULL;
return;
}
mCallbacksObj = env->NewGlobalRef(object);
}
其中btInf = getBluetoothInterface()
//com_android_bluetooth_btservice_AdapterService.cpp
const bt_interface_t* getBluetoothInterface() {
}
而这个sBluetoothInterface又是在
static void classInitNative(JNIEnv* env, jclass clazz) {
int err;
hw_module_t* module;
jclass jniCallbackClass =
env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
"Lcom/android/bluetooth/btservice/JniCallbacks;");
method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
"adapterPropertyChangedCallback",
"([I[[B)V");
method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
"discoveryStateChangeCallback", "(I)V");
method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
"devicePropertyChangedCallback",
"([B[I[[B)V");
method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
"([B[BI)V");
method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
"([B[BIII)V");
method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
"bondStateChangeCallback", "(I[BI)V");
method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
"aclStateChangeCallback", "(I[BI)V");
char value[PROPERTY_VALUE_MAX];
property_get("bluetooth.mock_stack", value, "");
const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
err = hw_get_module(id, (hw_module_t const**)&module);
if (err == 0) {
hw_device_t* abstraction;
err = module->methods->open(module, id, &abstraction);
if (err == 0) {
bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
sBluetoothInterface = btStack->get_bluetooth_interface();
} else {
ALOGE("Error while opening Bluetooth library");
}
} else {
ALOGE("No Bluetooth Library found");
}
}
中被初始化的,所以,最后返回的是一个
btStack->get_bluetooth_interface();类型为bt_interface_t
然后强制转换成了bthh_interface_t类型
我们看一下:bt_interface_t
再看一下:bthh_interface_t
觉得这样强制转换有点奇怪
typedef struct {
struct hw_device_t common;
const bt_interface_t* (*get_bluetooth_interface)();
} bluetooth_device_t;
typedef bluetooth_device_t bluetooth_module_t;
也可以知道btStack的本质是一个bluetooth_device_t类型的结构体。
而这个结构体的来源从:
hw_device_t* abstraction;
err = module->methods->open(module, id, &abstraction);
知道,这个后续再深究
同样的,这里的get_bluetooth_interface的实现,也是被方案商封装起来的。
这个get_profile_interface就是硬件抽象层的实现:
./system/bluetooth/bluedroid/bluetooth.c
总结一下sBluetoothHidInterface->connect((bt_bdaddr_t *) addr))的整个过程:
sBluetoothHidInterface->connect((bt_bdaddr_t *) addr))=
(bthh_interface_t *)btInf->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=
(bthh_interface_t *)getBluetoothInterface()->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=
(bthh_interface_t *)sBluetoothInterface->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=
(bthh_interface_t *)btStack->get_bluetooth_interface()->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=
(bthh_interface_t *)(bluetooth_module_t *)abstraction->get_bluetooth_interface()->get_profile_interface(BT_PROFILE_HIDHOST_ID)) ->connect((bt_bdaddr_t *) addr))=
可以知道:
1.调用bluetooth_module_t中的get_bluetooth_interface返回一个bt_interface_t
//Bluetooth.h
typedef struct {
struct hw_device_t common;
const bt_interface_t* (*get_bluetooth_interface)();
} bluetooth_device_t;
typedef bluetooth_device_t bluetooth_module_t;
2.调用bt_interface_t的get_profile_interface(BT_PROFILE_HIDHOST_ID)) 并将其转换成bthh_interface_t *类型
//bluetooth.h
typedef struct {
size_t size;
int (*init)(bt_callbacks_t* callbacks );
int (*enable)(void);
int (*disable)(void);
void (*cleanup)(void);
int (*get_adapter_properties)(void);
int (*get_adapter_property)(bt_property_type_t type);
int (*set_adapter_property)(const bt_property_t *property);
int (*get_remote_device_properties)(bt_bdaddr_t *remote_addr);
int (*get_remote_device_property)(bt_bdaddr_t *remote_addr, bt_property_type_t type);
int (*set_remote_device_property)(bt_bdaddr_t *remote_addr,const bt_property_t *property);
int (*get_remote_service_record)(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid);
int (*get_remote_services)(bt_bdaddr_t *remote_addr);
int (*start_discovery)(void);
int (*cancel_discovery)(void);
int (*create_bond)(const bt_bdaddr_t *bd_addr);
int (*remove_bond)(const bt_bdaddr_t *bd_addr);
int (*cancel_bond)(const bt_bdaddr_t *bd_addr);
int (*pin_reply)(const bt_bdaddr_t *bd_addr, uint8_t accept,
uint8_t pin_len, bt_pin_code_t *pin_code);
int (*ssp_reply)(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant,
uint8_t accept, uint32_t passkey);
const void* (*get_profile_interface) (const char *profile_id);
int (*dut_mode_configure)(uint8_t enable);
int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len);
int (*enter_headless_mode)(void);
int (*add_headless_mode_wakeup_device)(bt_bdaddr_t *remote_addr);
int (*delete_headless_mode_wakeup_device)(bt_bdaddr_t *remote_addr);
} bt_interface_t;
3.调用bthh_interface_t里的connect函数进行连接:
typedef struct {
size_t size;
bt_status_t (*init)( bthh_callbacks_t* callbacks );
bt_status_t (*connect)( bt_bdaddr_t *bd_addr);
bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );
bt_status_t (*virtual_unplug)(bt_bdaddr_t *bd_addr);
bt_status_t (*set_info)(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info );
bt_status_t (*get_protocol) (bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode);
bt_status_t (*set_protocol)(bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode);
bt_status_t (*get_report)(bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, uint8_t reportId, int bufferSize);
bt_status_t (*set_report)(bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, char* report);
bt_status_t (*send_data)(bt_bdaddr_t *bd_addr, char* data);
bt_status_t (*ota_get_fwversion)(bt_bdaddr_t *bd_addr);
bt_status_t (*ota_update_firmware)(bt_bdaddr_t *bd_addr, char* path);
void (*cleanup)( void );
} bthh_interface_t;
现在我们要看一下bthh_interface_t的connect实现是在哪里。
我们调试的时候会发现看打印,其实已经掉到了蓝牙协议栈里:
I/bt-btif ( 1133): btif_hh_handle_evt: event=0
D/bt-btif ( 1133): btif_hh_connect: a=20:73:14:01:16:8b
I/bt-btif ( 1133): BTHH: btif_hh_connect
D/bt-btif ( 1133): btif_hh_find_dev_by_bda: a=20:73:14:01:16:8b
D/bt-btif ( 1133): btif_hh_find_dev_by_bda: not found
D/CachedBluetoothDevice( 1044): Command sent successfully:CONNECT Address:20:73:14:01:16:8B Profile:HID
D/bt-btif ( 1133): btif_hh_find_dev_available:
D/bt-btif ( 1133): btif_hh_find_dev_available: found 0
D/BTIF_HH ( 1133): HAL bt_hh_callbacks->connection_state_cb
D/BTIF_HH ( 1133): HAL bt_hh_callbacks->connection_state_cb
I/bt-l2cap( 1133): 02:09:35.340 L2CAP SENT Command. Name: L2C Connection Request (0x02) ID 0x0a, len 4
I/bt-l2cap( 1133): 02:09:35.340 Channel ID : 01
I/bt-l2cap( 1133): 02:09:35.340 PSM : 0x1
I/bt-l2cap( 1133): 02:09:35.340 Source CID : 0x45
I/bt-l2cap( 1133): 02:09:35.340 --
查找 btif_hh_connect
chenglan@novatek:~/Android_NT667B/android$ grep -rn btif_hh_connect
Binary file .svn/pristine/d1/d110e9293da57287f57d20647f4180042c28578a.svn-base matches
.svn/pristine/c5/c5822f31e14e3040d6fddf1b557ba44308bb1ecd.svn-base:108:extern int btif_hh_connect(bt_bdaddr_t *bd_addr);
.svn/pristine/c5/c5822f31e14e3040d6fddf1b557ba44308bb1ecd.svn-base:385: status = btif_hh_connect(bd_addr);
.svn/pristine/64/6442e055874f6f42cf0bf0131db726440d4117b8.svn-base:559:** Function btif_hh_connect
.svn/pristine/64/6442e055874f6f42cf0bf0131db726440d4117b8.svn-base:567:bt_status_t btif_hh_connect(bt_bdaddr_t *bd_addr)
.svn/pristine/64/6442e055874f6f42cf0bf0131db726440d4117b8.svn-base:1060: ret = btif_hh_connect(bd_addr);
Binary file device/novatek/nt72668_tcl/bluetooth/bluetooth.default.so matches
external/bluetooth/bluedroid/btif/src/btif_dm.c:108:extern int btif_hh_connect(bt_bdaddr_t *bd_addr);
external/bluetooth/bluedroid/btif/src/btif_dm.c:385: status = btif_hh_connect(bd_addr);
external/bluetooth/bluedroid/btif/src/btif_hh.c:560:** Function btif_hh_connect
external/bluetooth/bluedroid/btif/src/btif_hh.c:568:bt_status_t btif_hh_connect(bt_bdaddr_t *bd_addr)
external/bluetooth/bluedroid/btif/src/btif_hh.c:1061: ret = btif_hh_connect(bd_addr);
Binary file out/target/product/nt72668_tcl/system.img matches
Binary file out/target/product/nt72668_tcl/system_ext4.img matches
Binary file out/target/product/nt72668_tcl/obj/PACKAGING/systemimage_intermediates/system.img matches
Binary file out/target/product/nt72668_tcl/system/lib/hw/bluetooth.default.so matches
而在btif_hh.c中由connect函数开始调,调到btif_hh_handle_evt再调到btif_hh_connect才有了上述打印,而这个connect函数的注册时在下面这个结构体中:上面的一大段分析,其实调到的就是这个bthh_interface_t类型的bthhInterface的connect函数。
static const bthh_interface_t bthhInterface = {
sizeof(bt_interface_t),
init,
connect,
disconnect,
virtual_unplug,
set_info,
get_protocol,
set_protocol,
// get_idle_time,
// set_idle_time,
get_report,
set_report,
send_data,
cleanup,
};
我们现在看下这个btif_hh.c中的connect:
static bt_status_t connect( bt_bdaddr_t *bd_addr)
{
if(btif_hh_cb.status != BTIF_HH_DEV_CONNECTING)
{
btif_transfer_context(btif_hh_handle_evt, BTIF_HH_CONNECT_REQ_EVT,
(char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
return BT_STATUS_SUCCESS;
}
else
return BT_STATUS_BUSY;
}
这里我们跟踪下btif_transfer_context,看里面做了什么
bt_status_t btif_transfer_context (tBTIF_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTIF_COPY_CBACK *p_copy_cback)
{
tBTIF_CONTEXT_SWITCH_CBACK *p_msg;
BTIF_TRACE_VERBOSE2("btif_transfer_context event %d, len %d", event, param_len);
if ((p_msg = (tBTIF_CONTEXT_SWITCH_CBACK *) GKI_getbuf(sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len)) != NULL)
{
p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT;
p_msg->p_cb = p_cback;
p_msg->event = event;
if (p_copy_cback)
{
p_copy_cback(event, p_msg->p_param, p_params);
}
else if (p_params)
{
memcpy(p_msg->p_param, p_params, param_len);
}
btif_sendmsg(p_msg);
return BT_STATUS_SUCCESS;
}
else
{
return BT_STATUS_NOMEM;
}
}
void btif_sendmsg(void *p_msg)
{
// Called by applications to send a buffer to a task
GKI_send_msg(BTIF_TASK, BTU_BTIF_MBOX, p_msg);
}
不去发送这个消息之后是怎么处理的,但猜测应该是调用了btif_hh_handle_evt:
因为消息类型是BTIF_HH_CONNECT_REQ_EVT,所以执行的代码应该是:
case BTIF_HH_CONNECT_REQ_EVT:
{
ret = btif_hh_connect(bd_addr);
if(ret == BT_STATUS_SUCCESS)
{
HAL_CBACK(bt_hh_callbacks, connection_state_cb,bd_addr,BTHH_CONN_STATE_CONNECTING);
}
else
HAL_CBACK(bt_hh_callbacks, connection_state_cb,bd_addr,BTHH_CONN_STATE_DISCONNECTED);
}
break;
这个函数会一直调用下去,调用到btif_hh_connect,在btif_hh_connect中又会调用到
btif_hh_find_dev_by_bda,这个函数的作用是:
Return the device pointer of the specified bt_bdaddr_t
在btif_hh_connect中调用玩btif_hh_find_dev_by_bda之后,又会调用HAL_CBACK(bt_hh_callbacks, connection_state_cb, bd_addr, BTHH_CONN_STATE_CONNECTING);
我们看下btif_hh_connect中连接相关的主要代码:
//这个added_dev类型是HAL层里定义好的
btif_hh_added_device_t *added_dev = NULL;
//for循环的作用是根据地址bd_addr得到匹配的设备
for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
if (memcmp(&(btif_hh_cb.added_devices[i].bd_addr), bd_addr, BD_ADDR_LEN) == 0) {
added_dev = &btif_hh_cb.added_devices[i];
BTIF_TRACE_WARNING3("%s: Device %s already added, attr_mask = 0x%x",
__FUNCTION__, bda_str, added_dev->attr_mask);
}
}
//如果设备存在,但不可用,则打印一个提示
if (added_dev != NULL) {
if (added_dev->dev_handle == BTA_HH_INVALID_HANDLE) {
// No space for more HID device now.
BTIF_TRACE_ERROR2("%s: Error, device %s added but addition failed", __FUNCTION__, bda_str);
memset(&(added_dev->bd_addr), 0, 6);
added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
return BT_STATUS_FAIL;
}
}
//如果设备可连接
if (added_dev == NULL ||
(added_dev->attr_mask & HID_NORMALLY_CONNECTABLE) != 0 ||
(added_dev->attr_mask & HID_RECONN_INIT) == 0)
{
tBTA_SEC sec_mask = BTUI_HH_SECURITY;
btif_hh_cb.status = BTIF_HH_DEV_CONNECTING;
BD_ADDR *bda = (BD_ADDR*)bd_addr;
BTA_HhOpen(*bda, BTA_HH_PROTO_RPT_MODE, sec_mask);
}
我们跟踪下这个BTA_HhOpen
bta/hh/bta_hh_api.c
void BTA_HhOpen(BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode, tBTA_SEC sec_mask)
{
tBTA_HH_API_CONN *p_buf;
p_buf = (tBTA_HH_API_CONN *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_CONN));
if (p_buf!= NULL)
{
memset((void *)p_buf, 0, sizeof(tBTA_HH_API_CONN));
p_buf->hdr.event = BTA_HH_API_OPEN_EVT;
p_buf->hdr.layer_specific = BTA_HH_INVALID_HANDLE;
p_buf->sec_mask = sec_mask;
p_buf->mode = mode;
bdcpy(p_buf->bd_addr, dev_bda);
bta_sys_sendmsg((void *)p_buf);
}
else
{
APPL_TRACE_ERROR0("No resource to send HID host Connect request.");
}
}
这里调用到了:
void bta_sys_sendmsg(void *p_msg)
{
GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);
}
这个函数还是只用了一个地址
gki/common/gki_buffer.c
void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg)
{
BUFFER_HDR_T *p_hdr;
tGKI_COM_CB *p_cb = &gki_cb.com;
if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD))
{
GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
GKI_freebuf (msg);
return;
}
#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
if (gki_chk_buf_damage(msg))
{
GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
return;
}
#endif
p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE);
if (p_hdr->status != BUF_STATUS_UNLINKED)
{
GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
return;
}
GKI_disable();
if (p_cb->OSTaskQFirst[task_id][mbox])
p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
else
p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
p_hdr->p_next = NULL;
p_hdr->status = BUF_STATUS_QUEUED;
p_hdr->task_id = task_id;
GKI_enable();
GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox));
return;
}
gki/ulinux/gki_ulinux.c
UINT8 GKI_send_event (UINT8 task_id, UINT16 event)
{
GKI_TRACE("GKI_send_event %d %x", task_id, event);
if (task_id < GKI_MAX_TASKS)
{
pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[task_id]);
gki_cb.com.OSWaitEvt[task_id] |= event;
pthread_cond_signal(&gki_cb.os.thread_evt_cond[task_id]);
pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[task_id]);
GKI_TRACE("GKI_send_event %d %x done", task_id, event);
return ( GKI_SUCCESS );
}
GKI_TRACE("############## GKI_send_event FAILED!! ##################");
return (GKI_FAILURE);
}
发送消息,不知道发送到哪里去了 = =
蓝牙打开关闭全过程跟踪:
http://www.aiuxian.com/article/p-1886156.html
分析了这么长,还是没有找到到底什么时候判定为连接上的,我们搜索BTHH_CONN_STATE_CONNECTED
发现
//---------------------------这里讨论callback来更新连接状态的过程
这个bt_hh_callbacks是在init函数中被初始化的:
static bt_status_t init( bthh_callbacks_t* callbacks )
{
UINT32 i;
BTIF_TRACE_EVENT1("%s", __FUNCTION__);
bt_hh_callbacks = callbacks;
memset(&btif_hh_cb, 0, sizeof(btif_hh_cb));
for (i = 0; i < BTIF_HH_MAX_HID; i++){
btif_hh_cb.devices[i].dev_status = BTHH_CONN_STATE_UNKNOWN;
}
btif_enable_service(BTA_HID_SERVICE_ID);
return BT_STATUS_SUCCESS;
}
从Log
D/BTIF_HH ( 1133): HAL bt_hh_callbacks->connection_state_cb
D/BTIF_HH ( 1133): HAL bt_hh_callbacks->connection_state_cb
中分析,结合HAL_CBACK的定义,应该是调用到了bt_hh_callbacks->connection_state_cb
而这个bt_hh_callbacks类型是bthh_callbacks_t,其定义在include/hardware/bt_hh.h中
typedef struct {
size_t size;
bthh_connection_state_callback connection_state_cb;
bthh_hid_info_callback hid_info_cb;
bthh_protocol_mode_callback protocol_mode_cb;
bthh_idle_time_callback idle_time_cb;
bthh_get_report_callback get_report_cb;
bthh_virtual_unplug_callback virtual_unplug_cb;
bthh_audio_state_callback audio_state_cb;
bthh_ota_version_callback ota_version_cb;
bthh_ota_update_callback ota_update_cb;
bthh_ota_updatedone_callback ota_updatedone_cb;
} bthh_callbacks_t;
这里调用的是一个callback函数 bthh_connection_state_callback connection_state_cb;
而这个connection_state_cb是在哪里指定的呢?
我们grep -rn bthh_callbacks_t可以发现:
com_android_bluetooth_hid.cpp:209:
static bthh_callbacks_t sBluetoothHidCallbacks = {
sizeof(sBluetoothHidCallbacks),
connection_state_callback,
NULL,
get_protocol_mode_callback,
NULL,
NULL,
virtual_unplug_callback,
audio_state_callback,
ota_get_version_callback,
ota_update_progress_callback,
ota_update_done_callback
};
这个bthh_callbacks_t结构体里面的connection函数是connection_state_callback
所以,其实又调用到这里来了,而这个结构体的初始化是在com_android_bluetooth_hid.classInitNative()中讲其传进去进行初始化的。
status = sBluetoothHidInterface->init(&sBluetoothHidCallbacks)
所以现在回调就会调用到这里:
static void connection_state_callback(bt_bdaddr_t *bd_addr, bthh_connection_state_t state) {
jbyteArray addr;
CHECK_CALLBACK_ENV
addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
if (!addr) {
ALOGE("Fail to new jbyteArray bd addr for HID channel state");
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
return;
}
sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectStateChanged, addr, (jint) state);
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
sCallbackEnv->DeleteLocalRef(addr);
}
这个method_onConnectStateChanged类型是jmethodID,发现其实这里用到的是C++调用Android的机制。这里回调到了onConnectStateChanged函数,查找一下可以发现在HidService.java,PanService.java等文件中都有这个函数的定义。其实这些回调函数里只是发送了一个消息,然后HidService监听到之后做了处理,这里是发送了一个MESSAGE_CONNECT_STATE_CHANGED消息来更新连接状态:
D/HidService( 1133): MESSAGE_CONNECT_STATE_CHANGED newState:1, prevState:0
在Log中,我们发现btif之后是l2cap的log,那么我们现在要看下怎么调到l2cap中去的。
这个l2cap是一个协议栈,在目录external/bluetooth/bluedroid/stack/l2cap下:
//----------------------------------现在我们看下协议栈中队/uhid这个节点的操作情况--------------
在bluedroid/btif/co/bta_hh_co.c中有对这个设备节点的相应操作函数:
我们跟uhid_write这个函数被bta_hh_co_send_hid_info调用,被btif_hh_upstreams_evt调用(btif_hh.c)
收到 BTA_HH_GET_DSCP_EVT事件的时候会执行,
在btif_hh.c中有一个函数bte_hh_evt:
static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data)
{
bt_status_t status;
int param_len = 0;
if (BTA_HH_ENABLE_EVT == event)
param_len = sizeof(tBTA_HH_STATUS);
else if (BTA_HH_OPEN_EVT == event)
param_len = sizeof(tBTA_HH_CONN);
else if (BTA_HH_DISABLE_EVT == event)
param_len = sizeof(tBTA_HH_STATUS);
else if (BTA_HH_CLOSE_EVT == event)
param_len = sizeof(tBTA_HH_CBDATA);
else if (BTA_HH_GET_DSCP_EVT == event)
param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event)|| (BTA_HH_GET_IDLE_EVT == event))
param_len = sizeof(tBTA_HH_HSDATA);
else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) || (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
param_len = sizeof(tBTA_HH_CBDATA);
else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event) )
param_len = sizeof(tBTA_HH_DEV_INFO);
else if (BTA_HH_API_ERR_EVT == event)
param_len = 0;
status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event, (void*)p_data, param_len, NULL);
ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
}
这个函数就是作event转换的
而调用这个函数的地方是在:
bt_status_t btif_hh_execute_service(BOOLEAN b_enable)
{
if (b_enable)
{
BTA_HhEnable(BTA_SEC_NONE, FALSE, bte_hh_evt);
}
else {
BTA_HhDisable();
}
return BT_STATUS_SUCCESS;
}
BTA_HhEnable是在bta/hh/bta_hh_api.c中的,这个函数是注册hid host
47
60 void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback)
61 {
62 tBTA_HH_API_ENABLE *p_buf;
63
64
65 GKI_sched_lock();
66 bta_sys_register(BTA_ID_HH, &bta_hh_reg);
67 GKI_sched_unlock();
68
69 APPL_TRACE_ERROR0("Calling BTA_HhEnable");
70 p_buf = (tBTA_HH_API_ENABLE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_ENABLE));
71
72 if (p_buf != NULL)
73 {
74 memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));
75
76 p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
77 p_buf->p_cback = p_cback;
78 p_buf->sec_mask = sec_mask;
79
80 bta_sys_sendmsg(p_buf);
81 }
82 }
83
所以在注册hid host的时候,绑定了这个消息处理函数,因此后面收到消息的时候,会通过这个函数调用btif_hh_upstreams_evt来对设备节点进行操作,将相应的事件注入到设备节点,以与驱动进行事件交互。
而注册host的地方是在这里:btif_dm.c中
bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id,
BOOLEAN b_enable)
{
switch (service_id)
{
case BTA_HFP_SERVICE_ID:
case BTA_HSP_SERVICE_ID:
{
btif_hf_execute_service(b_enable);
}break;
case BTA_A2DP_SERVICE_ID:
{
btif_av_execute_service(b_enable);
}break;
case BTA_HID_SERVICE_ID:
{
btif_hh_execute_service(b_enable);
}break;
default:
BTIF_TRACE_ERROR1("%s: Unknown service being enabled", __FUNCTION__);
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
}
而btif_hh_execute_service是在btif_dm.c中执行的。
我们后续看下到底bta_hh_co.c中的函数对这个设备节点都做了哪些事情。
先在的问题是,在HAL层,蓝牙协议栈是怎么使用的呢?
我们分析上面的过程:
bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
sBluetoothInterface = btStack->get_bluetooth_interface();
为什么蓝牙协议栈是一个bluetooth_module_t的形式呢?
还有就是蓝牙协议层,是怎么和驱动层交流的
现在看下,蓝牙手柄上的按钮消息是怎么传到android系统的:
dumpsys可以知道:
5: Broadcom Bluetooth HID
Classes: 0x8000014b
Path: /dev/input/event5
Descriptor: 15d4b0db1b56c4af5d6eb4d517f062fed0422482
Location:
UniqueId:
Identifier: bus=0x0005, vendor=0x1038, product=0x1412, version=0x001b
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
我们操纵蓝牙手柄的时候发现这样的信息:
[ 5600.559211] input: Broadcom Bluetooth HID as /devices/virtual/misc/uhid/input6
[ 5600.569201] hid-generic 0005:1038:1412.0003: input,hidraw1: BLUETOOTH HID v0.1b Mouse [Broadcom Bluetooth HID] on
Hid设备的注册:
http://www.aiuxian.com/article/p-251750.html
http://www.aiuxian.com/article/p-251788.html
//-------------------------------------Android HAL层------------------------------------------------
百度文库,对android蓝牙连接流程的介绍:
http://wenku.baidu.com/link?url=Wli_9D7k5bPU7Q-Rh1WtuLL2AhE8szYEcXrOyilR6E_0EqCGJb6wJlN-LCKkSeFUeN9t70hsfP3uMQ2_XihHrH-xnq9Mmn9VznODqxU6Dou
这里有对Android HAL层的讲解:
http://www.cnblogs.com/armlinux/archive/2012/01/14/2396768.html
/hardware/libhardware/modules 目录下定义了很多硬件模块
/hardware/msm7k /hardware/qcom /hardware/ti /device/Samsung
/device/moto 各个厂商平台相关的hal
这些硬件模块都编译成xxx.xxx.so,目标位置为/system/lib/hw目录
1.在Bluetooth.h中定义了蓝牙模块的ID
#define BT_STACK_MODULE_ID "bluetooth"
2.com_android_bluetooth_btservice_AdapterService.cpp中根据这个ID获取蓝牙模块,参数module是硬件模块地址(相当于是一个指针)
err = hw_get_module(id, (hw_module_t const**)&module);
3.获得模块之后,打开这个硬件设备
hw_device_t* abstraction;
err = module->methods->open(module, id, &abstraction);
上述的module->methods->open这个open函数就是HAL提供的接口,其函数原型在hardware.h头文件中有定义,只能返回struct hw_device_t类型的指针,而在JNI方法中,我们关心的是struct hello_device_t,只有通过struct hello_device_t,我们才能获取其所有的成员函数(接HAL提供的接口函数),由于struct hello_device_t的第一个成员就是struct hw_device_t类型的数据,因此在这里可以将获取的struct hw_device_t强制转化为struct hello_device_t来用。
具体参看:
http://www.open-open.com/lib/view/open1325474434250.html
针对
hw_device_t* abstraction;
err = module->methods->open(module, id, &abstraction);
if (err == 0) {
bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
sBluetoothInterface = btStack->get_bluetooth_interface();
我们看下abstraction的来源:
err = hw_get_module(id, (hw_module_t const**)&module);
//Hardware.c
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int status;
int i;
const struct hw_module_t *hmi = NULL;
char prop[PATH_MAX];
char path[PATH_MAX];
char name[PATH_MAX];
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
for (i=0 ; i
if (i < HAL_VARIANT_KEYS_COUNT) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, prop);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, prop);
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH1, name);
if (access(path, R_OK) == 0) break;
}
}
status = -ENOENT;
if (i < HAL_VARIANT_KEYS_COUNT+1) {
status = load(class_id, path, module);
}
return status;
}
cat /proc/bus/input/devices得到:
I: Bus=0005 Vendor=1038 Product=1412 Version=001b
N: Name="Broadcom Bluetooth HID"
P: Phys=
S: Sysfs=/devices/virtual/misc/uhid/input5
U: Uniq=
H: Handlers=sysrq kbd mouse4 event5
B: PROP=0
B: EV=12001f
B: KEY=110 4000 0 0 0 6 fc810 2050000 0 ffff0000 70000 fc2124a8 20f ff9f30fa c14057ff febeffdf ffefffff ffefffff fffffffe
B: REL=103
B: ABS=100 30027
B: MSC=10
B: LED=1f
这就是这个博通蓝牙HID的信息
系统调用和驱动的关系:
HAL层框架的搭建:
Bluedroid架构:
http://www.aiuxian.com/article/p-298280.html
bluetooth services和bluetooth JNI编译出来的结果就是bluetooth.apk, bluetooth services透过bluetooth JNI,bluetooth JNI透过硬件抽象层,直接调用到bluedroid的核心协议栈,而核心协议栈通过uart driver,rfkill driver,UHID,TUN等vfs文件接口直接调用到内核空间的驱动。
Android蓝牙下层驱动
/dev/input # ls
event0
/dev/input # [ 8075.222116] input: Broadcom Bluetooth HID as /devices/virtual/misc/uhid/input5
[ 8075.232058] hid-generic 0005:1038:1412.0002: input,hidraw1: BLUETOOTH HID v0.1b Mouse [Broadcom Bluetooth HID] on
/dev/input #
/dev/input #
/dev/input # ls
event0
event1
从上面的打印可以知道,在/dev/input目录下生产了一个event5的节点
与event对应的相关设备信息位于/proc/bus/input/devices
cat devices可以找到这个设备的信息:
I: Bus=0005 Vendor=1038 Product=1412 Version=001b
N: Name="Broadcom Bluetooth HID"
P: Phys=
S: Sysfs=/devices/virtual/misc/uhid/input5
U: Uniq=
H: Handlers=sysrq kbd mouse4 event5
B: PROP=0
B: EV=12001f
B: KEY=110 4000 0 0 0 6 fc810 2050000 0 ffff0000 70000 fc2124a8 20f ff9f30fa c14057ff febeffdf ffefffff ffefffff fffffffe
B: REL=103
B: ABS=100 30027
B: MSC=10
B: LED=1f
知道还有一个目录,是:
./sys/devices/virtual/misc/uhid/input5
这个设备节点应该是uhid驱动注册的