代码位置: frameworks/base/services/java/com/android/server/BluetoothManagerService.java 这部分代码,生成libandroid_runtime.so 完成功能,中转BluetoothAdapter和Bluetooth.apk,所有来自其他应用的请求,都通过IBluetooth接口,转发到Bluetooth.apk 启动方式: Intent i = new Intent(IBluetooth.class.getName()); if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE,
UserHandle.USER_CURRENT)) { 这里IBluetooth.class.getName实际返回android.bluetooth.IBluetooth 这个action正好是packages/app/Bluetooth/AdapterService要处理的action。 BluetoothManagerService保持一个BluetoothServiceConnection的回调,当AdapterService启动时,就可以拿到IBluetooth接口了。
代码位置: packages/apps/Bluetooth 这部分代码,生成Bluetooth.apk 完成功能: 1、IBluetooh.aidl的服务端,由AdapterService的内部类AdapterServiceBinder实现 2、在BluetoothManagerService调用IBluetooth接口时,实际上是在AdapterServiceBinder端来处理。 3、IBluetooth.enable ->AdapterServiceBinder->enable ->BluetoothManagerService.enable BluetoothManagerService初始化了一个蓝牙状态机AdapterState实例,mAdapterStateMachine,调用enable是给状态机发一个消息AdapterState.USER_TURN_ON 4、再往下层的调用是通过,AdapterService的JNI接口enableNative
代码位置: packages/apps/Bluetooth/jni 这部分代码,是AdapterService的JNI实现 完成功能: 1、获取bluetooth.default接口,这个接口是android获取HAL的通用方式, err = hw_get_module(id, (hw_module_t const**)&module); 2、因此调用JNIenableNative实际是调用bluetooth.default的实现enable
蓝牙关闭过程: 1、客户端调用AdapterService.java的disable接口 2、AdapterService给AdapterStateMachine发送一个USER_TURN_OFF的Message 3、AdapterStateMachine调用AdapterProperties的onBluetoothDisable接口 4、AdapterProperties把scan mode设置为AbstractionLayer.BT_SCAN_MODE_NONE 5、AdapterProperties调用AdapterService的setAdapterPropertyNative接口,往底层调用 6、在JNI层com_android_bluetooth_btservice_AdapterServices的setAdapterPropertyNative,调用蓝牙HAL接口sBluetoothInterface->set_adapter_property(&prop); 7、蓝牙HAL接口的实现,在external/bluetooth/bluedroid/btif/src/bluetooth.c中 8、bluetooth.c ::set_adapter_property -> btif_core.c :: btif_set_adapter_property 9、btif_set_adapter_property对属性BT_PROPERTY_ADAPTER_SCAN_MODE设置的处理,先保存discovery mode为BTA_DM_NON_DISC,表示不可发现,保存connecable mode为BTA_DM_NON_CONN,表示不可连接。然后,调用external/bluetooth/bluedroid/bta/dm/bta_dm_api.c :: BTA_DmSetVisibility方法 10、BTA_DmSetVisibility构造一个tBTA_DM_API_SET_VISIBILITY *p_msg,填入discovery mode, connetiable mode等参数,然后调用external/bluetooth/bluedroid/bta/sys/bta_sys_main.c ::bta_sys_sendmsg 11、bta_sys_sendmsg调用external/bluetooth/bluedroid/gki/common/gki_buffer.c :: GKI_send_msg发送一条GKI信息到BTA,GKI_send_msg有三个参数,第一个参数是线程id,也作为task id, 通过bta_sys_init获得,第二个参数是mailbox id,第三个是上一步封装好的p_msg 12、GKI_send_msg首先对p_msg进一步封装成event,通过链表存到mailbox id对应的任务队列中,调用external/bluetooth/bluedroid/gki/ulinux/gki_ulinux.c ::GKI_send_event进行发送 13、GKI_send_event设置事件掩码gki_cb.com.OSWaitEvt[task_id] |= event;, 通过pthread_cond_signal(&gki_cb.os.thread_evt_cond[task_id]);通知另外线程。 14、这样,在另外一个等待线程函数中gki_ulinux.c ::GKI_wait可以返回了,现在来看这个等待线程是怎么起来的
在调用HAL接口bluetoothInterface集合中的init的时候, 1、btif/src/bluetooth.c ::init 会调用btif/src/btif_core.c ::btif_init_bluetooth 启动一个BTIF任务 2、btif_init_bluetooth 调用gki/ulinux/gki_ulinux.c ::GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR, (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),
sizeof(btif_task_stack)); 启动这个任务,第一个参数btif_task是任务处理函数,第二个参数是task id,第三个是对应string表示形式,第四个是任务列表的起始指针,第四个是任务栈最大深度。 3、GKI_create_task 启动一个线程,等待任务事件 ret = pthread_create( &gki_cb.os.thread_id[task_id], //保存了线程id &attr1,
(void *)gki_task_entry,
&gki_pthread_info[task_id]); //gki_pthread_info保存了任务信息:task_id,task_entry。
可向而知,刚刚创建的任务线程,就是那个等待线程,来看gki_task_entry,即是btif_task的实现: btif/src/btif_core.c 1、因为我们已经要开始等待事件了,因此要通知JAVA/JNI层,记得刚刚我们有注册了回调,那么就通过宏HAL_CBACK(bt_hal_cbacks, thread_evt_cb, ASSOCIATE_JVM);来通知JNI 2、进入for(;;) 3、调用GKI_wait,等待一个事件的返回 4、判断事件 event == BT_EVT_TRIGGER_STACK_INIT,如果是,就调用BTA_EnableBluetooth(bte_dm_evt)初始化蓝牙芯片组 5、判断事件event & EVENT_MASK(GKI_SHUTDOWN_EVT,如果是,就对出任务循环 6、判断事件event & TASK_MBOX_1_EVT_MASK 判断是否是1好mbox里面的事件。 7、如果第6步满足判断事件,那么判断事件event &BT_EVT_CONTEXT_SWITCH_EVT,如果是,调用btif_context_switched(p_msg)切换上下文 8、回第三步
到这里,很奇怪,为什么没有我们要处理的事件,难道在另外的任务线程里面处理? 在回过头来,看GKI对TASK_MBOX, TASK_MBOX_EVT_MASK的规划 TIMER事件,TASK事件,APPL事件(应用程序请求事件?)
gki/common/gki.h #define TASK_MBOX_0 0
#define TASK_MBOX_1 1
#define TASK_MBOX_2 2
#define TASK_MBOX_3 3

#define NUM_TASK_MBOX 4
#define MAX_EVENTS 16

#define TASK_MBOX_0_EVT_MASK 0x0001
#define TASK_MBOX_1_EVT_MASK 0x0002
#define TASK_MBOX_2_EVT_MASK 0x0004
#define TASK_MBOX_3_EVT_MASK 0x0008
/* Definitions of task IDs for inter-task messaging */
#ifndef BTU_TASK
#define BTU_TASK 0
#endif

#ifndef BTIF_TASK
#define BTIF_TASK 1
#endif

#ifndef A2DP_MEDIA_TASK
#define A2DP_MEDIA_TASK 2
#endif

/* The number of GKI tasks in the software system. */
#ifndef GKI_MAX_TASKS
#define GKI_MAX_TASKS 3
#endif
在第11步bta_sys_sendmsg调用GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg); 他的TASK_ID就是bta_sys_cb.task_id,现在看下这个task_id的初始化过程,也就是BTA系统的初始化过程 BTA的初始化,要从在BTU的任务处理函数(btu_task)中开始的,那么btu_task又是怎么起来的, 这就要从bt开启的时候说起了。 1、在开启蓝牙之时,JNI调用HAL接口bluetoothInterface的enable函数,即btif/src/btif_core.c ::btif_enable_bluetooth 2、btif_enable_bluetooth调用main/bte_main.c的BTE API函数bte_main_enable(btif_local_bd_addr.address); 其从bte task,这个address怎么来的? 3、bte_main_enable,首先,初始化BTE控制块(HCI相关回调) 4、调用hci接口,(替代4.1的hciattach进程?),给bt设备上电。 5、GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR, (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),
sizeof(bte_btu_stack)); //启动BTU任务 6、pthread_create( &timer_thread_id,
&timer_attr,
timer_thread,
NULL); //根据NO_GKI_RUN_RETURN是否执行timer_thread线程,NO_GKI_RUN_RETURN是什么意思?LINUX是否需要定义此宏?
再来看btu_task的实现: 1、btu_init_core(); 初始化核心control block,比如BTU, BTM, L2CAP, and SDP 2、BTE_InitStack();初始化BTE控制块,比如RFCOMM, DUN, SPP, HSP2, HFP, OBX, BIP 3、#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE) //初始化BTA bta_sys_init();
#endif 4、#if ( BT_USE_TRACES==TRUE ) //此宏用于调试,是否设置? BTE_InitTraceLevels();
#endif 5、进入for(;;) 6、处理事件的列表://为什么不是全部? TASK_MBOX_0_EVT_MASK TIMER_0_EVT_MASK TIMER_1_EVT_MASK TIMER_2_EVT_MASK RPCGEN_MSG_EVT TASK_MBOX_2_EVT_MASK EVENT_MASK(APPL_EVT_7) //APPL_EVT_7事件 再来看bta_sys_init的实现 bta/sys/bta_sys_main.c bta_sys_init //注意到这里并没有建一个bta_task 1、bta_sys_cb.task_id = GKI_get_taskid(); //获取taskid,是什么? 这里的GKI_get_taskid()仅是调用pthread_self()获取pthread_t,那么这段代码很明显是跟btu_task是同一个pthread,因此发给bta_sys_cb.task_id自然而然的由btu_task来处理了。
再回过头来看bta_sys_sendmsg的实现 void bta_sys_sendmsg(void *p_msg)
{
GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);
}
这里GKI_send_msg的第一个参数已经确定,第二个参数见BTA相关参数的映射: BTA相关映射关系如下: /* GKI task mailbox event for BTA. */
#ifndef BTA_MBOX_EVT
#define BTA_MBOX_EVT TASK_MBOX_2_EVT_MASK
#endif

/* GKI task mailbox for BTA. */
#ifndef BTA_MBOX
#define BTA_MBOX TASK_MBOX_2
#endif

/* GKI timer id used for protocol timer for BTA. */
#ifndef BTA_TIMER
#define BTA_TIMER TIMER_1
#endif

const tBTA_SYS_CFG bta_sys_cfg =
{
BTA_MBOX_EVT, /* GKI mailbox event */
BTA_MBOX, /* GKI mailbox id */
BTA_TIMER, /* GKI timer id */
APPL_INITIAL_TRACE_LEVEL /* initial trace level */
};

tBTA_SYS_CFG *p_bta_sys_cfg = (tBTA_SYS_CFG *)&bta_sys_cfg;
那么第二个参数也确定下来了,就是TASK_MBOX_2

再回过头来看btu_task处理的时间列表,里面正包含了TASK_MBOX_2_EVT_MASK
这样,我们终于找到处理设置BT_PROPERTY_ADAPTER_SCAN_MODE的债主了,就是btu_task 再来看btu_task对TASK_MBOX_2_EVT_MASK的实现 if (event & TASK_MBOX_2_EVT_MASK)
{
while ((p_msg = (BT_HDR *) GKI_read_mbox(TASK_MBOX_2)) != NULL) //取出p_msg
{
bta_sys_event(p_msg); //处理p_msg
}
}
也就是说bta_sys_event会调用子系统回调函数去处理p_msg,看怎么实现的。bta/sys/bta_sys_main.c :: bta_sys_event BTA_API void bta_sys_event(BT_HDR *p_msg) //这里名字也正好与BTA对应上 1、UINT8 id = (UINT8) (p_msg->event >> 8); 获取id 右移8位 2、 if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) { freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg); } 3、再看当初event的形成 void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode, UINT8 pairable_mode, UINT8 conn_filter ) p_msg->hdr.event = BTA_DM_API_SET_VISIBILITY_EVT; 4、BTA_DM_API_SET_VISIBILITY_EVT的取值定义在bta/dm/bta_dm_int.h enum
{
/* device manager local device API events */
BTA_DM_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_DM), //注意这里BTA_SYS_EVT_START(BTA_ID_DM)实现#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id));因为BTA_ID_DM是1, BTA_DM_API_DISABLE_EVT,
BTA_DM_API_SET_NAME_EVT,
BTA_DM_API_SET_VISIBILITY_EVT,
BTA_DM_API_SET_AFH_CHANNELS_EVT,
BTA_API_DM_SIG_STRENGTH_EVT,
BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT,
BTA_DM_API_TX_INQPWR_EVT,
BTA_DM_ACL_CHANGE_EVT,
BTA_DM_API_ADD_DEVICE_EVT, ... }; 5、因此计算刚才的id,也是1
BTA_ID_DM的回调函数的注册的过程 1、还记得btif_task刚起来的时候,会等待一个BT_EVT_TRIGGER_STACK_INIT的事件,对那个事件的处理,就是调用BTA_EnableBluetooth进行初始化硬件。 if (event == BT_EVT_TRIGGER_STACK_INIT)
{
BTIF_TRACE_DEBUG0("btif_task: received trigger stack init event");
BTA_EnableBluetooth(bte_dm_evt);
} 2、bta/dm/bta_dm_api.c ::tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback) 在这里面,注册两个子系统处理回调 bta_sys_register (BTA_ID_DM, &bta_dm_reg ); bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg ); 那么,我们来看他的定义 static const tBTA_SYS_REG bta_dm_reg = {
bta_dm_sm_execute, bta_dm_sm_disable };
那么,bta_dm_sm_execute正是bta_sys_event要调用的实现
bta_dm_sm_execute的实现: 1、UINT16 event = p_msg->event & 0x00ff; //获得event事件,BTA_DM_API_SET_VISIBILITY_EVT 2、 (*bta_dm_action[event])( (tBTA_DM_MSG*) p_msg); 调用这个函数来处理 3、bta_dm_action列表: const tBTA_DM_ACTION bta_dm_action[] =
{

/* device manager local device API events */
bta_dm_enable, /* 0 BTA_DM_API_ENABLE_EVT */
bta_dm_disable, /* 1 BTA_DM_API_DISABLE_EVT */
bta_dm_set_dev_name, /* 2 BTA_DM_API_SET_NAME_EVT */
bta_dm_set_visibility, /* 3 BTA_DM_API_SET_VISIBILITY_EVT */
bta_dm_set_afhchannels, /* 4 BTA_DM_API_SET_AFH_CHANNELS_EVT */
bta_dm_signal_strength, /* 5 BTA_API_DM_SIG_STRENGTH_EVT */
bta_dm_vendor_spec_command,/* 6 BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT */
bta_dm_tx_inqpower, /* 7 BTA_DM_API_SIG_STRENGTH_EVT */
bta_dm_acl_change, /* 8 BTA_DM_ACL_CHANGE_EVT */
bta_dm_add_device, /* 9 BTA_DM_API_ADD_DEVICE_EVT */
... } 4、也就是说调用bta_dm_set_visibility来实现。
bta_dm_set_visibility的实现bta/dm/bta_dm_act.c 1、BTM_SetDiscoverability((UINT8)p_data->set_visibility.disc_mode, bta_dm_cb.inquiry_scan_window,
bta_dm_cb.inquiry_scan_interval); //调用这个实现设置discoverymode BTM_SetDeviceClass (cod);//DEV_CLASS cod封装好discory mode btsnd_hcic_write_dev_class (dev_class); //stack/hcic/hcicmds.c 2、BTM_SetConnectability((UINT8)p_data->set_visibility.conn_mode,
bta_dm_cb.page_scan_window,
bta_dm_cb.page_scan_interval); //调用这个实现设置canmode btsnd_hcic_write_scan_enable (scan_mode); //stack/hcic/hcicmds.c 3、btsnd_hcic_write_dev_class和btsnd_hcic_write_scan_enable都会将参数封包,通过cmd方式,调用btu_hcif_send_cmd发送出去。
btu_hcif_send_cmd的实现: 1、首先取出命令控制块 tHCI_CMD_CB * p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]); 2、p_hci_cmd_cb->cmd_window = p_hci_cmd_cb->cmd_xmit_q.count + 1; //打开发送窗口 3、while (p_hci_cmd_cb->cmd_window != 0) { ... p_buf = (BT_HDR *)GKI_dequeue (&(p_hci_cmd_cb->cmd_xmit_q)); //从链表中取出一个消息 btu_hcif_store_cmd(controller_id, p_buf); //保存发出去的消息,用于超时机制 GKI_enqueue(&(p_hci_cmd_cb->cmd_cmpl_q), p_cmd); // 拷贝到链表中 btu_start_timer (&(p_hci_cmd_cb->cmd_cmpl_timer), (UINT16)(BTU_TTYPE_BTU_CMD_CMPL + controller_id),
BTU_CMD_CMPL_TIMEOUT); //启动计时器, cmd_cmpltimer与cmd_cmpl_q的关系? p_hci_cmd_cb->cmd_window--; //计数器减一
if (controller_id == LOCAL_BR_EDR_CONTROLLER_ID)
{
HCI_CMD_TO_LOWER(p_buf); //发送到底层,是一个宏
}
... } 4、HCI_CMD_TO_LOWER的宏定义 bluedroid/include/bt_target.h:#define HCI_CMD_TO_LOWER(p) bte_main_hci_send((BT_HDR *)(p), BT_EVT_TO_LM_HCI_CMD); 来看bte_main_hci_send的实现: 1、UINT16 sub_event = event & BT_SUB_EVT_MASK;//利用子事件掩码,BT_EVT_TO_LM_HCI_CMD &BT_SUB_EVT_MASK = 0 2、 if((sub_event == LOCAL_BR_EDR_CONTROLLER_ID) || \ (sub_event == LOCAL_BLE_CONTROLLER_ID))
bt_hc_if->transmit_buf((TRANSAC)p_msg, \
(char *) (p_msg + 1), \
p_msg->len); //调用transmit_buf接口发送出去。
bt_hc_if是在HCI初始化的过程中得到的。
HCI初始化过程 在调用HAL接口bluetoothInterface集合中的init的时候, 1、btif/src/bluetooth.c ::init 会调用btif/src/btif_core.c ::btif_init_bluetooth 2、btif_init_bluetooth 会调用main/bte_main.c :: bte_main_boot_entry //初始化BT芯片的入口 3、bte_main_boot_entry调用 bte_main_in_hw_init 或许HCI接口 static bt_hc_interface_t * bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface(); static const bt_hc_callbacks_t bt_hc_callbacks; //回调,跟bt_hc_if调用方向刚好相反 4、hci/src/bt_hci_bdroid.c中 const bt_hc_interface_t *bt_hc_get_interface(void) {
return &bluetoothHCLibInterface; //返回接口列表 } 4、在使能蓝牙调用bte_main_enable的时候,开始btu_stack之前,会按顺序初始化蓝牙设备。 bt_hc_if->init(&hc_callbacks, local_addr); //hc_callbacks是hci回调 bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);
bt_hc_if->preload(NULL); 5、bt_hc_if->init也就是调用bluetoothHCLibInterface的init方法 来看bluetoothHCLibInterface的init方法hci/src/bt_hci_bdroid.c 1、bt_hc_callbacks_t *bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb; //保存回调 2、init_vnd_if(local_bdaddr);//调用厂商库里面的bt_vendor_interface_t *接口,初始化蓝牙设备 3、p_hci_if = &hci_h4_func_table; //使用HCIH4接口回调 4、p_hci_if->init(); //调用hci_h4_func_table的init方法,初始化H4模块 5、userial_init();//初始化uart数据结构 6、lpm_init();//初始化低功耗模块,调用bt_vendor_interface_t的op接口 7、utils_queue_init(&tx_q); //初始化发送队列 8、pthread_create(&hc_cb.worker_thread, &thread_attr, \ bt_hc_worker_thread, NULL) != 0) //起工作线程
在回过头来看transmit_buf,其实就是调用bluetoothHCLibInterface的transmit_buf方法 看transmit_buf的实现:hci/src/bt_hci_bdroid.c static int transmit_buf(TRANSAC transac, char *p_buf, int len)
{
utils_enqueue(&tx_q, (void *) transac); //链接到发送队列

bthc_signal_event(HC_EVENT_TX); //广播事件

return BT_HC_STATUS_SUCCESS;
}
另外一边的工作线程bt_hc_worker_thread,接收到上面的广播事件之后会判断事件类型,如果是HC_EVENT_TX,首先将目前所有的时间加入到数组sending_msg_que里面 for(i = 0; i < sending_msg_count; i++) p_hci_if->send(sending_msg_que[i]); //调用p_hci_if的send接口发送出去。
上面已经提到p_hci_if的send接口在hci_h4_func_table中实现,hci/src/hci_h4.c 来看其send回调的实现 void hci_h4_send_msg(HC_BT_HDR *p_msg) { ... if (event == MSG_STACK_TO_HC_HCI_CMD) type = H4_TYPE_COMMAND; //设定cmd类型 if (sub_event == LOCAL_BR_EDR_CONTROLLER_ID) {
acl_data_size = h4_cb.hc_acl_data_size;
acl_pkt_size = h4_cb.hc_acl_data_size + HCI_ACL_PREAMBLE_SIZE; //设置数据大小
} ... bytes_sent = userial_write(event,(uint8_t *) p, bytes_to_send);//写串口, 是否会阻塞
... bt_hc_cbacks->tx_result((TRANSAC) p_msg, (char *) (p_msg + 1), \ BT_HC_TX_SUCCESS); //将发送结果通过回调发回去,注意这里只是成功发送到串口,有没有成功,应该是从内核往上发,由userial_read_thread来完成。
来看读线程userial_read_thread的实现 static void *userial_read_thread(void *arg) { while (userial_running) { //调用回调申请一段消息BUFFER p_buf = (HC_BT_HDR *) bt_hc_cbacks->alloc( \
BTHC_USERIAL_READ_MEM_SIZE); //select读取串口消息 rx_length = select_read(userial_cb.fd, p, READ_LIMIT); //将消息发到rx队列,并广播出去 utils_enqueue(&(userial_cb.rx_q), p_buf);
bthc_signal_event(HC_EVENT_RX); //调用回调释放内存
bt_hc_cbacks->dealloc((TRANSAC) p_buf, (char *) (p_buf + 1));
} }
工作线程bt_hc_worker_thread得到广播之后 if (events & HC_EVENT_RX)
{
p_hci_if->rcv(); //调用rcv,也就是hci_h4_func_table的hci_h4_receive_msg回调
} hci_h4_receive_msg有一个rcv_state变量,表征当前数据帧的收取状态 typedef enum {
H4_RX_MSGTYPE_ST,
H4_RX_LEN_ST,
H4_RX_DATA_ST,
H4_RX_IGNORE_ST
} tHCI_H4_RCV_STATE;
通过条件p_cb->rcv_msg_type和acl_rx_frame_end_chk()两个条件,判断当前是否收完一帧数据,如果是,则调用bt_hc_cbacks的data_ind回调把数据上发: bt_hc_cbacks->data_ind((TRANSAC) p_cb->p_rcv_msg, \
(char *) (p_cb->p_rcv_msg + 1), \
p_cb->p_rcv_msg->len + BT_HC_HDR_SIZE);

bt_hc_cbacks的data_ind回调,就是main/bte_main.c hc_callbacks的data_ind函数,来看它的实现 static int data_ind(TRANSAC transac, char *p_buf, int len)
{
BT_HDR *p_msg = (BT_HDR *) transac;
GKI_send_msg (BTU_TASK, BTU_HCI_RCV_MBOX, transac); //发到btu task中去了,而且mbox为TASK_MBOX_0 //因为如下宏 //#define BTU_HCI_RCV_MBOX TASK_MBOX_0 /* Messages from HCI */
return BT_HC_STATUS_SUCCESS;
}

那么在btu task中: 比较事件验码为BT_EVT_TO_BTU_HCI_EVT后, 进而调用btu_hcif.c的btu_hcif_process_event处理来自底层的事件上报,在 会取出event code,不同的code,调用不同的函数来处理,以HCI_PAGE_SCAN_REP_MODE_CHNG_EVT为例子,它的处理函数为btu_hcif_page_scan_rep_mode_chng_evt,这样,再一层层, 这里应该报上两个事件btif_adapter_properties_evt,一个是discovery mode一个是connectiable mode,是否保证到JAVA的通路是畅通的?

在写属性的过程中,往串口写是一方面,在写完串口之后,还需要更新本地数据库。(要是BT模块写拒绝怎么办?) 在btif/src/btif_core.c :: btif_set_adapter_property 中,最后一步 if (storage_req_id != BTIF_CORE_STORAGE_NO_ACTION) //判断是否需要更新数据库
{
int btif_status;
/* pass on to storage for updating local database */

memset(&(req.write_req.bd_addr), 0, sizeof(bt_bdaddr_t));
memcpy(&(req.write_req.prop), property, sizeof(bt_property_t));
//btif_transfer_context会将一个消息到BTU_BTIF_MBO,也就是TASK_MBOX_1信箱,并且这个消息 // 由btif_task来处理
return btif_transfer_context(execute_storage_request,
storage_req_id,
(char*)&req,
sizeof(btif_storage_req_t)+property->len,
btif_in_storage_request_copy_cb); btif_sendmsg(p_msg) GKI_send_msg(BTIF_TASK, BTU_BTIF_MBOX, p_msg);
}

来看btif的处理: if(event & TASK_MBOX_1_EVT_MASK) { //计算掩码,符合 while((p_msg = GKI_read_mbox(BTU_BTIF_MBOX)) != NULL) { //取出消息 switch (p_msg->event) {
case BT_EVT_CONTEXT_SWITCH_EVT: //判断消息类型,符合
btif_context_switched(p_msg); //处理消息
break;
... } } }
来看btif_context_switched的实现: static void btif_context_switched(void *p_msg)
{
tBTIF_CONTEXT_SWITCH_CBACK *p= (tBTIF_CONTEXT_SWITCH_CBACK *) p_msg;
/* each callback knows how to parse the data */
if (p->p_cb)
p->p_cb(p->event, p->p_param); //取出事件处理回调函数,也就是execute_storage_request
}

来看execute_storage_request的实现 static void execute_storage_request(UINT16 event, char *p_param) { switch(event){
case BTIF_CORE_STORAGE_ADAPTER_WRITE: //判断事件类型,符合
{
btif_storage_req_t *p_req = (btif_storage_req_t*)p_param; bt_property_t *p_prop = &(p_req->write_req.prop);
status = btif_storage_set_adapter_property(p_prop); //是否会阻塞? HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, status, 1, p_prop); //调用JNI测的回调 } ... } }
而在JAVA一侧,通过AdapterProperties.java的回调adapterPropertyChangedCallback,可以得知刚才property设置的结果(是否从串口发上来的?): case: AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE: mService.startBluetoothDisable 1、调用AdapterService的startBluetoothDisable方法 2、AdapterService给AdapterStateMachine发送AdaterState.BEGIN_DISABLE的Message 3、AdapterStateMachine调用AdapterService的disableNative接口
adapterPropertyChangedCallback回调,通过com_android_bluetooth_btservice_AdapterService.cpp调用JAVA的方式,调用 在JNI一层,有一组回调接口,是通过Android HAL层组织的 bt_callbacks_t sBluetoothCallbacks = {
sizeof(sBluetoothCallbacks),
adapter_state_change_callback,
adapter_properties_callback,
remote_device_properties_callback,
device_found_callback,
discovery_state_changed_callback,
pin_request_callback,
ssp_request_callback,
bond_state_changed_callback,
acl_state_changed_callback,
callback_thread_event,
}; 这组回调,通过sBluetoothInterface->init(&sBluetoothCallbacks);注册。 而sBluetoothInterface的实现,在external/bluetooth/bluedroid/btif/src const bt_interface_t* bluetooth__get_bluetooth_interface ()
{
return &bluetoothInterface;
} static const bt_interface_t bluetoothInterface = {
sizeof(bt_interface_t),
init,
enable,
disable,
cleanup,
get_adapter_properties,
get_adapter_property,
set_adapter_property,
get_remote_device_properties,
get_remote_device_property,
set_remote_device_property,
get_remote_service_record,
get_remote_services,
start_discovery,
cancel_discovery,
create_bond,
remove_bond,
cancel_bond,
pin_reply,
ssp_reply,
get_profile_interface,
dut_mode_configure,
dut_mode_send
}; 在init里面,会将sBluetoothInterface保存在bluetoothInterface中,
因此,反响调用的顺序是这样的 1、bluetoothInterface->adapter_properties_cb也就是com_android_bluetooth_btservice_AdapterService的adapter_properties_cb 2、adapter_properties_callback调用AdapterProperties的adapterPropertyChangedCallback方法
现在看btif_storage_set_adapter_property的实现,研究一下事件是怎么写入NVRAM中去。 btif/src/btif_storage.c bt_status_t btif_storage_set_adapter_property(bt_property_t *property)
{
return prop2cfg(NULL, property) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
btif/src/btif_storage.c static int prop2cfg(bt_bdaddr_t *remote_bd_addr, bt_property_t *prop) { switch(prop->type) { case BT_PROPERTY_ADAPTER_SCAN_MODE:
btif_config_set_int("Local", "Adapter",
BTIF_STORAGE_KEY_ADAPTER_SCANMODE, *(int*)prop->val);
break; ... } ...
} btif/src/btif_config.c int btif_config_set_int(const char* section, const char* key, const char* name, int value)
{
return btif_config_set(section, key, name, (char*)&value, sizeof(value), BTIF_CFG_TYPE_INT); //加上config类型
} btif/src/btif_config.c int btif_config_set(const char* section, const char* key, const char* name, const char* value, int bytes, int type)
{ ...
set_node(section, key, name, value, (short)bytes, (short)type); //找到一个cfg_node*(配置节点) btsock_thread_post_cmd(pth, CFG_CMD_SAVE, NULL, 0, 0); // pth是线程槽(thread slots)的序号。 ...
}
config node数据结构,root节点是所有配置的起始节点。 typedef struct cfg_node_s
{
const char* name;
union
{
struct cfg_node_s* child;
char* value;
};
short bytes;
short type;
short used;
short flag;
} cfg_node;

我理解的线程槽,BT中有很多业务,每一类的业余需要一个(或多个)额外的线程来处理一些事情,可以通过写线程槽的socket一端,那么读端在获取消息后,可以处理这些事情。 btif_init_bluetooth在创建btif_task之前,先会调用btif_config_init,初始config相关数据结构
btif/src/btif_config.c 1、stat(CFG_PATH, &st) //确认配置文件,路径:/data/misc/bluedroid/ 2、btsock_thread_init(); //初始化thread_slogtts数组 3、init_slot_lock(&slot_lock);//初始化线程锁 4、 root.name = "Bluedroid"; alloc_node(&root, CFG_GROW_SIZE);
dump_node("root", &root);
pth = btsock_thread_create(NULL, cfg_cmd_callback);
创建一个跟配置节点,并创捷一个取用一个线程槽,pth为ts数组里面对应的序号。 5、load_cfg(); //导入配置文件,读取xml文件到内存,以config_node形式组织起来。
先看btsock_thread_create的线程创建过程: int btsock_thread_create(btsock_signaled_cb callback, btsock_cmd_cb cmd_callback) 1、int h = alloc_thread_slot(); //获取一个空闲槽,卧槽,这是什么节奏 2、init_poll(h); //初始化这个槽点,创建一个socketpair,读写端分别是ts[h].cmd_fdr和ts[h].cmd_fdw,并且将cmd_fdr放入监听槽... 3、ts[h].thread_id = create_thread(sock_poll_thread, (void*)h); //给这个槽点创建线程,线程函数为sock_poll_thread 4、ts[h].callback = callback; ts[h].cmd_callback = cmd_callback; //sock_poll_thread将会调用它来处理写config
那么先来看写端的处理,也就是btsock_thread_post_cmd是怎么做的 btif/src/btif_sock_thread.c int btsock_thread_post_cmd(int h, int type, const unsigned char* data, int size, uint32_t user_id) sock_cmd_t cmd = {CMD_USER_PRIVATE, 0, type, size, user_id}; //将cmd包装到sock_cmd_t*cmd_send中 send(ts[h].cmd_fdw, cmd_send, size_send, 0) //直接往cmd_fdw写
再看来cmd_fdr,也就是sock_poll_thread的处理 btif/src/btif_sock_thread.c { for(;;)
{
prepare_poll_fds(h, pfds);
int ret = poll(pfds, ts[h].poll_count, -1); //开始监听
if(ret != 0)
{
int need_process_data_fd = TRUE;
if(pfds[0].revents) //cmd fd always is the first one
{
asrt(pfds[0].fd == ts[h].cmd_fdr);
if(!process_cmd_sock(h)) //先尝试处理cmd命令,即上面提到的CMD_USER_PRIVATE
{
APPL_TRACE_DEBUG1("h:%d, process_cmd_sock return false, exit...", h);
break;
}
if(ret == 1)
need_process_data_fd = FALSE;
else ret--; //exclude the cmd fd
}
if(need_process_data_fd)
process_data_sock(h, pfds, ret); //再处理数据。
}
else {APPL_TRACE_DEBUG1("no data, select ret: %d", ret)};
}
ts[h].thread_id = -1;
}
看process_cmd_sock的实现 btif/src/btif_sock_thread.c static int process_cmd_sock(int h)
{
sock_cmd_t cmd = {-1, 0, 0, 0, 0};
int fd = ts[h].cmd_fdr;
if(recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
{
APPL_TRACE_ERROR1("recv cmd errno:%d", errno);
return FALSE;
}
switch(cmd.id)
{
case CMD_USER_PRIVATE:
asrt(ts[h].cmd_callback);
if(ts[h].cmd_callback)
ts[h].cmd_callback(fd, cmd.type, cmd.flags, cmd.user_id); //调用回调处理,即上文的cfg_cmd_callback
break; ... }
return TRUE;
}

再来看cfg_cmd_callback的实现: static void cfg_cmd_callback(int cmd_fd, int type, int size, uint32_t user_id)
{
//BTIF_TRACE_DEBUG2("cmd type:%d, size:%d", type, size);
switch(type)
{
case CFG_CMD_SAVE:
lock_slot(&slot_lock);
save_cfg(); //保存所有的config到配置文件中,从根config node:root开始遍历
unlock_slot(&slot_lock);
break;
}
}

到目前为止蓝牙的关闭过程,才进行一般不到。 来看AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE被JNI调用到AdapterProperties.java的adapterPropertyChangedCallback之后怎么处理的 AdapterProperties.java adapterPropertyChangedCallback case AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE:
int mode = Utils.byteArrayToInt(val, 0);
mScanMode = mService.convertScanModeFromHal(mode);
intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
debugLog("Scan Mode:" + mScanMode);
if (mBluetoothDisabling) {
mBluetoothDisabling=false;
mService.startBluetoothDisable(); //调用服务的startBluetoothDisable停掉蓝牙设备
}
break;
AdapterService——com_android_bluetooth_btservice_AdapterService.cpp——bluetooth.c——btif_core.c 最终调用到btif_core.c的btif_disable_bluetooth,看btif_disable_bluetooth的实现 bt_status_t btif_disable_bluetooth(void) { btif_dm_on_disable();//终止配对 btif_core_state = BTIF_CORE_STATE_DISABLING; //将状态设置为BTIF_CORE_STATE_DISABLING btif_sock_cleanup(); //清理rfcomm & l2cap btif_pan_cleanup();
BTA_DisableBluetooth()//关闭蓝牙 btif_config_flush();//保存配置 } 先看btif_dm_on_disable的实现 btif/src/btif_sock.c void btif_dm_on_disable()
{
if (pairing_cb.state == BT_BOND_STATE_BONDING)
{
bt_bdaddr_t bd_addr;
bdcpy(bd_addr.address, pairing_cb.bd_addr);
btif_dm_cancel_bond(&bd_addr); 如果正在配对,则取消配对
}
}
btif_sock_cleanup和btif_pan_cleanup略过, 来看BTA_DisableBluetooth的实现: tBTA_STATUS BTA_DisableBluetooth(void)
{

BT_HDR *p_msg;

if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) //太暴力了,直接从BTA中拿出一条消息,
{
p_msg->event = BTA_DM_API_DISABLE_EVT; //然后改写事件。
bta_sys_sendmsg(p_msg);
}
else
{
return BTA_FAILURE;
}

return BTA_SUCCESS;
}

这个消息按照之前介绍过的,最终会被btu_task处理。来看处理过程 if (event & TASK_MBOX_2_EVT_MASK)
{
while ((p_msg = (BT_HDR *) GKI_read_mbox(TASK_MBOX_2)) != NULL)
{
bta_sys_event(p_msg);
}
}
上面依然讲过,bta_sys_event的消息处理回调是bta_dm_reg的bta_dm_sm_execute, BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg)
{
UINT16 event = p_msg->event & 0x00ff;

APPL_TRACE_EVENT1("bta_dm_sm_execute event:0x%x", event);

/* execute action functions */
if(event < BTA_DM_NUM_ACTIONS)
{
(*bta_dm_action[event])( (tBTA_DM_MSG*) p_msg); //BTA_DM_API_DISABLE_EVT对应的处理函数是bta_dm_disable
}

return TRUE;
}

来看bta_dm_disable的实现 void bta_dm_disable (tBTA_DM_MSG *p_data)
{
/* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after last channel is closed) */
L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0); //设置L2CAP通道超时时间

/* disable all active subsystems */
bta_sys_disable(BTA_SYS_HW_BLUETOOTH); //停掉BTA DM子系统

BTM_SetDiscoverability(BTM_NON_DISCOVERABLE, 0, 0);
BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0);//这两者上文解析过了

bta_dm_disable_pm();

bta_dm_cb.disabling = TRUE;

bta_dm_search_cancel(NULL); //停止搜寻设备

if(BTM_GetNumAclLinks()==0)
{
#if (defined(BTA_DISABLE_DELAY) && BTA_DISABLE_DELAY > 0)
/* If BTA_DISABLE_DELAY is defined and greater than zero, then delay the shutdown by
* BTA_DISABLE_DELAY milliseconds
*/
APPL_TRACE_WARNING2("%s BTA_DISABLE_DELAY set to %d ms",
__FUNCTION__, BTA_DISABLE_DELAY);
bta_sys_stop_timer(&bta_dm_cb.disable_timer);
bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_conn_down_timer_cback;
bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, BTA_DISABLE_DELAY);
#else
bta_dm_disable_conn_down_timer_cback(NULL);
#endif
}
else
{
bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 5000); //终止所有定时器的操作。
} }

先看bta_sys_disable(BTA_SYS_HW_BLUETOOTH)的实现,它调用子系统回调的bta_sys_cb.reg[bta_id]->disable方法,也就是上文的bta_dm_reg的其中的bta_dm_sm_disable方法 static const tBTA_SYS_REG bta_dm_reg =
{
bta_dm_sm_execute,
bta_dm_sm_disable
};
来看它的实现: void bta_dm_sm_disable( )
{
bta_sys_deregister( BTA_ID_DM );
}
void bta_sys_deregister(UINT8 id)
{
bta_sys_cb.is_reg[id] = FALSE;//只是简单的将is_reg赋值为FALSE
}

再来看bta_dm_search_cancel的实现 void bta_dm_search_cancel (tBTA_DM_MSG *p_data)
{

tBTA_DM_MSG * p_msg;

if(BTM_IsInquiryActive())
{
BTM_CancelInquiry(); //取消搜寻
bta_dm_search_cancel_notify(NULL);

if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
{
p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
bta_sys_sendmsg(p_msg); //给btu_task发消息

}
}
/* If no Service Search going on then issue cancel remote name in case it is active */
else if (!bta_dm_search_cb.name_discover_done)
{
BTM_CancelRemoteDeviceName();
}
#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
if (bta_dm_search_cb.gatt_disc_active)
{
bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
}
#endif
}

上面几步掠过,因为都是一些写过的消息线程间转发,到此为止停止蓝牙设备的工作已经接近尾声了 最后一步,是收尾工作,也就是btif_config_flush,来看它的实现: void btif_config_flush()
{
lock_slot(&slot_lock);
if(cached_change > 0)
save_cfg(); //保存配置到文件
unlock_slot(&slot_lock);
}

static int save_cfg()
{
const char* file_name = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT;
const char* file_name_new = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT_NEW;
const char* file_name_old = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT_OLD;
int ret = FALSE;
if(access(file_name_old, F_OK) == 0)
unlink(file_name_old); //删除缓存文件
if(access(file_name_new, F_OK) == 0)
unlink(file_name_new);
if(btif_config_save_file(file_name_new)) //保存最新配置到file_name_new,上文讲过了,就是根节点遍历config node数据结构,然后写入xml文件中。
{
cached_change = 0;
chown(file_name_new, -1, AID_NET_BT_STACK);
chmod(file_name_new, 0660);
rename(file_name, file_name_old);
rename(file_name_new, file_name); //更新配置到file_name
ret = TRUE;
}
else BTIF_TRACE_ERROR0("btif_config_save_file failed");
return ret;
}






更多相关文章

  1. Android(安卓)Handler类
  2. Android自定义Dialog弹框效果
  3. 关于Android中定时周期执行线程方法
  4. android之fragment与fragment、activity与activity、fragment与a
  5. android multicast 多播(组播)问题
  6. Android新组件应用
  7. Android日历操作
  8. Android里handler线程间的通信详解
  9. android避免回复出厂设置导致数据丢失的办法

随机推荐

  1. android添加以太网ethernet方法 android
  2. Android中的GPS应用开发入门教程
  3. Android应用程序框架层和系统运行库层日
  4. Eclipse开发Android常用快捷键
  5. android studio将一个项目作为module(libr
  6. Android Studio--Android中的消息机制
  7. Understanding Android Security(安卓安全
  8. 正确的Flutter和Android交互代码
  9. android进程间服务通信
  10. 关于android的9path图片处理