如何关闭android bt配对窗口,【转】Android 4.2 BT系统之蓝牙关闭过程全跟踪

代码位置:

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、因此调用JNI enableNative实际是调用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

#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

#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();//获取task id,是什么?

这里的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相关映射关系如下:

#ifndef BTA_MBOX_EVT

#define

BTA_MBOX_EVT TASK_MBOX_2_EVT_MASK

#endif

#ifndef BTA_MBOX

#define

BTA_MBOX TASK_MBOX_2

#endif

#ifndef BTA_TIMER

#define

BTA_TIMER TIMER_1

#endif

const tBTA_SYS_CFG bta_sys_cfg =

{

BTA_MBOX_EVT, BTA_MBOX, BTA_TIMER, APPL_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

{ 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[]

= { bta_dm_enable, bta_dm_disable, bta_dm_set_dev_name, bta_dm_set_visibility, bta_dm_set_afhchannels, bta_dm_signal_strength, bta_dm_vendor_spec_command,

bta_dm_tx_inqpower, bta_dm_acl_change, bta_dm_add_device,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值