蓝牙模块架构详解:https://blog.csdn.net/tronteng/article/details/53435217 html
蓝牙链接过程分析:http://mcu.szdahao.com/info/info_218.html java
因为公司想节约成本,将蓝牙盒子的功能由android来实现,可是发现android广播包的数据的拼组顺序与蓝牙盒子的不一致。因此须要看看源码是如何组包的,是否能够去修改。android
开启广播的源码
数组
》》注册客户端架构
|app
AdvertiseCallbackWrapper是BluetoothAdvertiser的内部类ide
|
oop
上面的mBluetoothGatt其实就是GattService的BluetoothGattBinder对象,可是注意广播的数据advertiseData并无往下传递。ui
|
this
Binder又调用了外部类GattService的方法
而后调用了Native的方法,调用到这里忽然发现TMD的广播包数据没有传递过来。因此往回看,搜索广播包存储的变量mAdertisment.
》》客户端注册成功,真正的开启广播
先调用binder的方法startMultiAdvertising
而后binder再调用service里的方法
能够看到广播的数据被封进了AdvertiseClient对象
service而后再调用AdvertiseManager的方法
|
|
调用AdvertiseNative方法,注意这个类是AdvertiseManager的内部类
先看单个广播的方法startSingleAdvertising:
第一步,先使能广播 。
第二步,设置广播的数据 。
看看JNI方法,注意是JNI,不是C。
注意上面的JNI方法env->GetByteArrayElements和ReleaseByteArrayElements,获取数组而后又释放了数组。因此主要看sGattIf->client->set_adv_data这个方法
搜索到这个方法的定义的h文件:
那么sGattIf是什么,client又是什么?这个方法的实如今哪里呢?
追溯sGattIf
追溯btIf
|
|
这个方法是在classInitNative方法里被调用的
那么classInitNative确定有个地方被用,咱们找找,注意这是jni类的方法,那么它确定是要被上层代码所调用的 :
|
|
能够发现classInitNative正好是GattService的本地方法,而且在GattService类加载时就调用了。观察GattService和com_android_bluetooth_btservice_AdapterService.cpp两个类,
发现它们也是在同一个应用下。因此上面方法调用推理是没有毛病的。
因此咱们接着上面的源码提及
上面引用调用十分复杂:
static void classInitNative(JNIEnv* env, jclass clazz) { int err; hw_module_t* module; char value[PROPERTY_VALUE_MAX]; //从配置文件里获取key = "bluetooth.mock_stack"的值 property_get("bluetooth.mock_stack", value, ""); //获得module的ID const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID); //给module赋值 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"); } }
上面的hw_get_module已经在和硬件打交道了
上面方法的调用就不去具体深究了,下面看看看 sBluetoothInterface这个变量的类型
它是bt_interface_t的指针类型,bt_interface_t的定义:
/** Represents the standard Bluetooth DM interface. */ typedef struct { /** set to sizeof(bt_interface_t) */ size_t size; /** * Opens the interface and provides the callback routines * to the implemenation of this interface. */ int (*init)(bt_callbacks_t* callbacks ); /** Enable Bluetooth. */ int (*enable)(void); /** Disable Bluetooth. */ int (*disable)(void); /** Closes the interface. */ void (*cleanup)(void); /** Get all Bluetooth Adapter properties at init */ int (*get_adapter_properties)(void); /** Get Bluetooth Adapter property of 'type' */ int (*get_adapter_property)(bt_property_type_t type); /** Set Bluetooth Adapter property of 'type' */ /* Based on the type, val shall be one of * bt_bdaddr_t or bt_bdname_t or bt_scanmode_t etc */ int (*set_adapter_property)(const bt_property_t *property); /** Get all Remote Device properties */ int (*get_remote_device_properties)(bt_bdaddr_t *remote_addr); /** Get Remote Device property of 'type' */ int (*get_remote_device_property)(bt_bdaddr_t *remote_addr, bt_property_type_t type); /** Set Remote Device property of 'type' */ int (*set_remote_device_property)(bt_bdaddr_t *remote_addr, const bt_property_t *property); /** Get Remote Device's service record for the given UUID */ int (*get_remote_service_record)(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid); /** Start SDP to get remote services */ int (*get_remote_services)(bt_bdaddr_t *remote_addr); /** Start Discovery */ int (*start_discovery)(void); /** Cancel Discovery */ int (*cancel_discovery)(void); /** Create Bluetooth Bonding */ int (*create_bond)(const bt_bdaddr_t *bd_addr, int transport); /** Remove Bond */ int (*remove_bond)(const bt_bdaddr_t *bd_addr); /** Cancel Bond */ int (*cancel_bond)(const bt_bdaddr_t *bd_addr); /** * Get the connection status for a given remote device. * return value of 0 means the device is not connected, * non-zero return status indicates an active connection. */ int (*get_connection_state)(const bt_bdaddr_t *bd_addr); /** BT Legacy PinKey Reply */ /** If accept==FALSE, then pin_len and pin_code shall be 0x0 */ int (*pin_reply)(const bt_bdaddr_t *bd_addr, uint8_t accept, uint8_t pin_len, bt_pin_code_t *pin_code); /** BT SSP Reply - Just Works, Numeric Comparison and Passkey * passkey shall be zero for BT_SSP_VARIANT_PASSKEY_COMPARISON & * BT_SSP_VARIANT_CONSENT * For BT_SSP_VARIANT_PASSKEY_ENTRY, if accept==FALSE, then passkey * shall be zero */ int (*ssp_reply)(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant, uint8_t accept, uint32_t passkey); /** Get Bluetooth profile interface */ const void* (*get_profile_interface) (const char *profile_id); /** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */ /* Configure DUT Mode - Use this mode to enter/exit DUT mode */ int (*dut_mode_configure)(uint8_t enable); /* Send any test HCI (vendor-specific) command to the controller. Must be in DUT Mode */ int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len); /** BLE Test Mode APIs */ /* opcode MUST be one of: LE_Receiver_Test, LE_Transmitter_Test, LE_Test_End */ int (*le_test_mode)(uint16_t opcode, uint8_t *buf, uint8_t len); /* enable or disable bluetooth HCI snoop log */ int (*config_hci_snoop_log)(uint8_t enable); /** Sets the OS call-out functions that bluedroid needs for alarms and wake locks. * This should be called immediately after a successful |init|. */ int (*set_os_callouts)(bt_os_callouts_t *callouts); /** Read Energy info details - return value indicates BT_STATUS_SUCCESS or BT_STATUS_NOT_READY * Success indicates that the VSC command was sent to controller */ int (*read_energy_info)(); /** * Native support for dumpsys function * Function is synchronous and |fd| is owned by caller. */ void (*dump)(int fd); /** * Clear /data/misc/bt_config.conf and erase all stored connections */ int (*config_clear)(void); } bt_interface_t;
能够知道bt_interface_t是个结构体类型
其实吧,源码看到这儿我又走偏了,咱们主要是分析set_adv_data是由那个类实现的
搜索这个方法的调用是很绕的
只能搜索一个bt_gatt_client.h文件,那么继续搜索bt_gatt_client.h文件
继续搜索bt_gatt.h文件
而后一个一个文件点进去搜索set_adv_data方法,发现只有/system/bt/btif/src/btif_gatt_client.c这个类里包涵这个方法,可是名字不是彻底如出一辙。
那么这个模块是怎么和外部模块创建关联的?用的什么机制?
搜索btgattClientInterface这个变量
|
搜索btif_gatt_get_interface方法
看看调用的方法:
这个好像就是蓝牙架构里的Profile层??
在bluetooth.c又将上面的get_profile_interface封装到bluetoothInterface
|
看看id
这不正是打开蓝牙栈吗?可是死活没有搜索到HAL_MODULE_INFO_SYM在哪里被调用。
看了这个博客https://blog.csdn.net/myarrow/article/details/7175204,应该就能明白。HAL如何向上层提供接口
回顾前面的源码
看看id
2个module的id如出一辙,这不正好与上面的HAL_MODULE_INFO_SYM这个Module不谋而合??????MD,分析源码,终于有一次合上了。
至此,咱们找到了方法的调用栈,但这不是个人目的。个人目的,还在set_adv_data那里。因此继续前面的源码接着说:
第1步:打包数据
就是把数据封装到adv_data这个变量里。
(client_ifbool set_scan_rspbool include_namebool include_txpowermin_intervalmax_intervalappearancemanufacturer_len* manufacturer_dataservice_data_len* service_dataservice_uuid_len* service_uuidbtif_adv_data_t *p_multi_adv_inst) { memset(p_multi_adv_instsizeof(btif_adv_data_t))p_multi_adv_inst->= (uint8_t) p_multi_adv_inst->= p_multi_adv_inst->= p_multi_adv_inst->= p_multi_adv_inst->= p_multi_adv_inst->= p_multi_adv_inst->= p_multi_adv_inst->= (manufacturer_len > ) { p_multi_adv_inst->p_manufacturer_data = GKI_getbuf()memcpy(p_multi_adv_inst->p_manufacturer_datamanufacturer_datamanufacturer_len)} p_multi_adv_inst->= (service_data_len > ) { p_multi_adv_inst->p_service_data = GKI_getbuf()memcpy(p_multi_adv_inst->p_service_dataservice_dataservice_data_len)} p_multi_adv_inst->= (service_uuid_len > ) { p_multi_adv_inst->p_service_uuid = GKI_getbuf()memcpy(p_multi_adv_inst->p_service_uuidservice_uuidservice_uuid_len)} }
第2步:标题待定
fixed_queue_enqueue是否是似曾相识
分析上面的回调方法应该是:
可知数据又发给了bta模块
可是bta又是在哪里接受这个消息的呢?
搜索BTA_DM_API_BLE_SET_ADV_CONFIG_EVT
搜索bta_dm_ble_set_adv_config
|
这个方法是至关的长啊,这个是组广播的方法能够确认无疑了。
再看看发送
看看下面这个方法的注释,发送命令给主机控制器。
其实到这里,广播包的数据已经拼组完成了。咱们就没有必要往下深究它怎么发出去了。