Android Bluetooth框架
一、Settings界面下scan
进入到android设置界面并打开蓝牙,扫描会自动开始。
下面我们从android蓝牙设置界面开始分析:
蓝牙开关按钮
BluetoothSettings.java (packages\apps\settings\src\com\android\settings\bluetooth)
public final class BluetoothSettings extends DeviceListPreferenceFragment implements Indexable
private BluetoothEnabler mBluetoothEnabler;
public void onActivityCreated(Bundle savedInstanceState)
mBluetoothEnabler = new BluetoothEnabler(activity, mSwitchBar);
mBluetoothEnabler.setupSwitchBar();
mSwitchBar.show(); // 显示蓝牙开关按钮
- 1
- 2
- 3
- 4
- 5
- 6
打开蓝牙
BluetoothEnabler.java (packages\apps\settings\src\com\android\settings\bluetooth)
onSwitchChanged()
mLocalAdapter.setBluetoothEnabled(isChecked);
- 1
- 2
打开蓝牙过程请参考我前面文章Android BlueDroid蓝牙enable过程,这里不做描述。蓝牙打开成功的状态会从协议栈回调上来,调用onBluetoothStateChanged,最终调用startScanning。
public void onBluetoothStateChanged(int bluetoothState) { super.onBluetoothStateChanged(bluetoothState); updateContent(bluetoothState); }
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">updateContent</span><span class="token punctuation">(</span><span class="token keyword">int</span> bluetoothState<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">final</span> PreferenceScreen preferenceScreen <span class="token operator">=</span> <span class="token function">getPreferenceScreen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> messageId <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span>bluetoothState<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">case</span> BluetoothAdapter<span class="token punctuation">.</span>STATE_ON<span class="token operator">:</span> preferenceScreen<span class="token punctuation">.</span><span class="token function">removeAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> preferenceScreen<span class="token punctuation">.</span><span class="token function">setOrderingAsAdded</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> mDevicePreferenceMap<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> mPairedDevicesCategory<span class="token punctuation">.</span><span class="token function">removeAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> mAvailableDevicesCategory<span class="token punctuation">.</span><span class="token function">removeAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>mInitialScanStarted<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token function">startScanning</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//启动扫描</span> mLocalAdapter<span class="token punctuation">.</span><span class="token function">startScanning</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
LocalBluetoothAdapter.java (packages\apps\settings\src\com\android\settings\bluetooth)
void startScanning(boolean force) {
if (!mAdapter.isDiscovering()) {
if (mAdapter.startDiscovery()) {
mLastScan = System.currentTimeMillis();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
BluetoothAdapter.java (frameworks\base\core\java\android\bluetooth)
public boolean startDiscovery() {
if (getState() != STATE_ON) return false;
try {
synchronized(mManagerCallback) {
if (mService != null) return mService.startDiscovery();
}
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
查看mService的定义:
private IBluetooth mService;
- 1
mService通过binder调用startDiscovery。
AdapterService.java(packages\apps\bluetooth\src\com\android\bluetooth\btservice)
public class AdapterService extends Service {
boolean startDiscovery() {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
return startDiscoveryNative();
}
private static class AdapterServiceBinder extends IBluetooth.Stub {
public boolean startDiscovery() {
AdapterService service = getService();
if (service == null) return false;
return service.startDiscovery();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
查看startDiscoveryNative的定义,可以看到它是一个native方法:
private native boolean startDiscoveryNative();
- 1
com_android_bluetooth_btservice_AdapterService.cpp (packages\apps\bluetooth\jni)
static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
int ret = sBluetoothInterface->start_discovery();
}
- 1
- 2
- 3
查看定义
static const bt_interface_t *sBluetoothInterface = NULL;
- 1
查找sBluetoothInterface的赋值,发现它加载了一个bluetooth.defualt.so模块:
#define BT_HARDWARE_MODULE_ID "bluetooth"
#define BT_STACK_MODULE_ID "bluetooth"
#define BT_STACK_TEST_MODULE_ID "bluetooth_test"
static void classInitNative(JNIEnv* env, jclass clazz)
{
hw_module_t* module;
const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID :
BT_STACK_TEST_MODULE_ID);
// 加载btStack模块 bluetooth.defualt.so
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) {
//最终转换为btStack结构体
bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
// sBluetoothInterface 赋值
sBluetoothInterface = btStack->get_bluetooth_interface();
} else {
ALOGE("Error while opening Bluetooth library");
}
} else {
ALOGE("No Bluetooth Library found");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
查看hw_get_module的定义:
Hardware.c (hardware\libhardware)
/** Base path of the hal modules */
#if defined(__LP64__)
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
#else
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#endif
/*
-
Check if a HAL with given name and subname exists, if so return 0, otherwise
-
otherwise return negative. On success path will contain the path to the HAL.
/
static int hw_module_exists(char path, size_t path_len, const char name,
const char subname)
{
snprintf(path, path_len, “%s/%s.%s.so”,
HAL_LIBRARY_PATH2, name, subname);
if (access(path, R_OK) == 0)
return 0;snprintf(path, path_len, “%s/%s.%s.so”,
HAL_LIBRARY_PATH1, name, subname);
if (access(path, R_OK) == 0)
return 0;return -ENOENT;
}
int hw_get_module(const char id, const struct hw_module_t module)
hw_get_module_by_class(id, NULL, module);
int hw_get_module_by_class(const char class_id, const char inst,
const struct hw_module_t *module)
{
char path[PATH_MAX];
char name[PATH_MAX];
strlcpy(name, class_id, PATH_MAX);
/* Nothing found, try the default */
// 查找模块 bluetooth.default.so
if (hw_module_exists(path, sizeof(path), name, “default”) == 0) {
goto found;
}
found:
return load(class_id, path, module);
void handle;
struct hw_module_t hmi;
handle = dlopen(path, RTLD_NOW);
/* Get the address of the struct hal_module_info. /
const char sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
Bluetooth.c (external\bluetooth\bluedroid\btif\src)
我们知道BlueDroid协议栈代码编译会 生成bluetooth.defualt.so模块,代码在external\bluetooth\bluedroid目录。
static const bt_interface_t bluetoothInterface
start_discovery,
btif_dm_start_discovery();
- 1
- 2
- 3
Btif_dm.c (external\bluetooth\bluedroid\btif\src)
bt_status_t btif_dm_start_discovery(void)
inq_params.mode = BTA_DM_GENERAL_INQUIRY;
inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION; // 扫描时间10*1.28 s
inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;
inq_params.report_dup = TRUE;
inq_params.filter_type = BTA_DM_INQ_CLR;
BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
p_msg->services = services;
p_msg->p_cback = p_cback;
p_msg->rs_res = BTA_DM_RS_NONE;
bta_sys_sendmsg(p_msg);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
btif_dm_start_discovery调用BTA_DmSearch,发送一个BTA_DM_API_SEARCH_EVT的消息,发出去的消息最后会在btu_task处理。
Bta_sys_main.c (external\bluetooth\bluedroid\bta\sys)
void bta_sys_sendmsg(void *p_msg)
{
GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);
GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox));
}
- 1
- 2
- 3
- 4
- 5
查看bta_sys_cb.task_id的赋值:
BTA_API void bta_sys_init(void)
bta_sys_cb.task_id = GKI_get_taskid();
- 1
- 2
bta_sys_init在btu_task中被调用,因此task_id 等于btu_task的task id,消息在btu_task中接收处理。
查看p_bta_sys_cfg->mbox的赋值:
// gki.h (external\bluetooth\bluedroid\gki\common)
/************************************************************************
** Mailbox definitions. Each task has 4 mailboxes that are used to
** send buffers to the task.
*/
#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
/************************************************************************
** Event definitions.
**
** There are 4 reserved events used to signal messages rcvd in task mailboxes.
** There are 4 reserved events used to signal timeout events.
** There are 8 general purpose events available for applications.
*/
#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
//bta_sys.h (external\bluetooth\bluedroid\bta\sys)
/* system manager configuration structure /
typedef struct
{
UINT16 mbox_evt; / GKI mailbox event /
UINT8 mbox; / GKI mailbox id /
UINT8 timer; / GKI timer id /
UINT8 trace_level; / initial trace level */
} tBTA_SYS_CFG;
// bta_sys_cfg.c (external\bluetooth\bluedroid\bta\sys)
/* GKI task mailbox event for BTA. */
#define BTA_MBOX_EVT TASK_MBOX_2_EVT_MASK
/* GKI task mailbox for BTA. */
#define BTA_MBOX TASK_MBOX_2
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
所以p_bta_sys_cfg->mbox等于TASK_MBOX_2, EVENT_MASK(mbox)则等于TASK_MBOX_2_EVT_MASK。
btu_task.c (external\bluetooth\bluedroid\stack\btu)
/******************************************************************************* ** ** Function btu_task ** ** Description This is the main task of the Bluetooth Upper Layers unit. ** It sits in a loop waiting for messages, and dispatches them ** to the appropiate handlers. ** ** Returns should never return ** *******************************************************************************/ BTU_API UINT32 btu_task (UINT32 param) { UINT16 event; BT_HDR *p_msg; UINT8 i; UINT16 mask; BOOLEAN handled;
<span class="token comment">/* Initialize the mandatory core stack control blocks (BTU, BTM, L2CAP, and SDP) */</span> <span class="token function">btu_init_core</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Initialize any optional stack components */</span> <span class="token function">BTE_InitStack</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
bta_sys_init(); // bta init
#endif
<span class="token comment">/* Send a startup evt message to BTIF_TASK to kickstart the init procedure */</span>
<span class="token function">GKI_send_event</span><span class="token punctuation">(</span>BTIF_TASK<span class="token punctuation">,</span> BT_EVT_TRIGGER_STACK_INIT<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/* Wait for, and process, events */</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
event <span class="token operator">=</span> GKI_wait <span class="token punctuation">(</span><span class="token number">0xFFFF</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&</span> TASK_MBOX_0_EVT_MASK<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token comment">/* Process all messages in the queue */</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&</span> TIMER_0_EVT_MASK<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token punctuation">}</span>
#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
if (event & TASK_MBOX_2_EVT_MASK)
{
while ((p_msg = (BT_HDR ) GKI_read_mbox(TASK_MBOX_2)) != NULL)
{
bta_sys_event(p_msg);
UINT8 id;
BOOLEAN freebuf = TRUE;
//event等于BTA_DM_API_SEARCH_EVT,id等于BTA_ID_DM_SEARCH,对应的cb函数bta_dm_search_reg(在btif_task->BTA_EnableBluetooth注册)
id = (UINT8) (p_msg->event >> 8);
//调用bta_dm_search_reg的bta_dm_search_sm_execute函数
freebuf = (bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
<span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&</span> TIMER_1_EVT_MASK<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token function">bta_sys_timer_update</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
#endif
if (event & TIMER_3_EVT_MASK) {
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&</span> <span class="token function">EVENT_MASK</span><span class="token punctuation">(</span>APPL_EVT_7<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
bta_dm_main.c (external\bluetooth\bluedroid\bta\dm)
bta_dm_search_sm_execute在bta_dm_search_action函数列表中取出BTA_DM_API_SEARCH对应的函数bta_dm_search_start并调用。
/* action function list */
const tBTA_DM_ACTION bta_dm_search_action[] =
{
bta_dm_search_start, /* 0 BTA_DM_API_SEARCH /
bta_dm_search_cancel, / 1 BTA_DM_API_SEARCH_CANCEL /
bta_dm_discover, / 2 BTA_DM_API_DISCOVER /
bta_dm_inq_cmpl, / 3 BTA_DM_INQUIRY_CMPL /
bta_dm_rmt_name, / 4 BTA_DM_REMT_NAME /
bta_dm_sdp_result, / 5 BTA_DM_SDP_RESULT /
bta_dm_search_cmpl, / 6 BTA_DM_SEARCH_CMPL /
bta_dm_free_sdp_db, / 7 BTA_DM_FREE_SDP_DB /
bta_dm_disc_result, / 8 BTA_DM_DISC_RESULT /
bta_dm_search_result, / 9 BTA_DM_SEARCH_RESULT /
bta_dm_queue_search, / 10 BTA_DM_QUEUE_SEARCH /
bta_dm_queue_disc, / 11 BTA_DM_QUEUE_DISC /
bta_dm_search_clear_queue, / 12 BTA_DM_SEARCH_CLEAR_QUEUE /
bta_dm_search_cancel_cmpl, / 13 BTA_DM_SEARCH_CANCEL_CMPL /
bta_dm_search_cancel_notify, / 14 BTA_DM_SEARCH_CANCEL_NOTIFY /
bta_dm_search_cancel_transac_cmpl, / 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL /
bta_dm_disc_rmt_name, / 16 BTA_DM_DISC_RMT_NAME /
bta_dm_di_disc / 17 BTA_DM_API_DI_DISCOVER */
#if BLE_INCLUDED == TRUE
,bta_dm_close_gatt_conn
#endif
};
BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg)
{
tBTA_DM_ST_TBL state_table;
UINT8 action;
int i;
<span class="token comment">/* look up the state table for the current state */</span>
state_table <span class="token operator">=</span> bta_dm_search_st_tbl<span class="token punctuation">[</span>bta_dm_search_cb<span class="token punctuation">.</span>state<span class="token punctuation">]</span><span class="token punctuation">;</span>
bta_dm_search_cb<span class="token punctuation">.</span>state <span class="token operator">=</span> state_table<span class="token punctuation">[</span>p_msg<span class="token operator">-</span><span class="token operator">></span>event <span class="token operator">&</span> <span class="token number">0x00ff</span><span class="token punctuation">]</span><span class="token punctuation">[</span>BTA_DM_SEARCH_NEXT_STATE<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">/* execute action functions */</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> BTA_DM_SEARCH_ACTIONS<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>action <span class="token operator">=</span> state_table<span class="token punctuation">[</span>p_msg<span class="token operator">-</span><span class="token operator">></span>event <span class="token operator">&</span> <span class="token number">0x00ff</span><span class="token punctuation">]</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">!=</span> BTA_DM_SEARCH_IGNORE<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token punctuation">(</span><span class="token operator">*</span>bta_dm_search_action<span class="token punctuation">[</span>action<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">(</span> <span class="token punctuation">(</span>tBTA_DM_MSG<span class="token operator">*</span><span class="token punctuation">)</span> p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span>
<span class="token punctuation">{<!-- --></span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> TRUE<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
Bta_dm_act.c (external\bluetooth\bluedroid\bta\dm)
void bta_dm_search_start (tBTA_DM_MSG *p_data)
{
result.status = BTM_StartInquiry( (tBTM_INQ_PARMS*)&p_data->search.inq_params,
bta_dm_inq_results_cb,
(tBTM_CMPL_CB*) bta_dm_inq_cmpl_cb);
}
- 1
- 2
- 3
- 4
- 5
- 6
Btm_inq.c (external\bluetooth\bluedroid\stack\btm)
BTM_StartInquiry函数的查询过程包括BLE和BR/EDR两种模式的查询,我们这里只关注BLE模式。p_inq->p_inq_results_cb是扫描回调指向bta_dm_inq_results_cb,扫描到广播后bta_dm_inq_results_cb将被调用。
tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb) { /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */ p_inq->inqparms = *p_inqparms;
<span class="token comment">/* Initialize the inquiry variables */</span> p_inq<span class="token operator">-</span><span class="token operator">></span>state <span class="token operator">=</span> BTM_INQ_ACTIVE_STATE<span class="token punctuation">;</span> p_inq<span class="token operator">-</span><span class="token operator">></span>p_inq_cmpl_cb <span class="token operator">=</span> p_cmpl_cb<span class="token punctuation">;</span> p_inq<span class="token operator">-</span><span class="token operator">></span>p_inq_results_cb <span class="token operator">=</span> p_results_cb<span class="token punctuation">;</span> p_inq<span class="token operator">-</span><span class="token operator">></span>inq_cmpl_info<span class="token punctuation">.</span>num_resp <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">/* Clear the results counter */</span> p_inq<span class="token operator">-</span><span class="token operator">></span>inq_active <span class="token operator">=</span> p_inqparms<span class="token operator">-</span><span class="token operator">></span>mode<span class="token punctuation">;</span>
#if BLE_INCLUDED == TRUE
/* start LE inquiry */
status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK), p_inqparms->duration)) != BTM_CMD_STARTED):
<span class="token keyword">return</span> status<span class="token punctuation">;</span>
#endif
/* start br/edr inquiry */
if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type,
&p_inqparms->filter_cond)) != BTM_CMD_STARTED)
p_inq->state = BTM_INQ_INACTIVE_STATE;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
Btm_ble_gap.c (external\bluetooth\bluedroid\stack\btm)
tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration) { if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) { btm_update_scanner_filter_policy(SP_ADV_ALL); status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE); }
<span class="token keyword">if</span> <span class="token punctuation">(</span>status <span class="token operator">==</span> BTM_CMD_STARTED<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> p_inq<span class="token operator">-</span><span class="token operator">></span>inq_active <span class="token operator">|</span><span class="token operator">=</span> mode<span class="token punctuation">;</span> p_ble_cb<span class="token operator">-</span><span class="token operator">></span>scan_activity <span class="token operator">|</span><span class="token operator">=</span> mode<span class="token punctuation">;</span> <span class="token function">BTM_TRACE_DEBUG</span><span class="token punctuation">(</span><span class="token string">"btm_ble_start_inquiry inq_active = 0x%02x"</span><span class="token punctuation">,</span> p_inq<span class="token operator">-</span><span class="token operator">></span>inq_active<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>duration <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">/* 启动inquiry timer */</span> btu_start_timer <span class="token punctuation">(</span><span class="token operator">&</span>p_inq<span class="token operator">-</span><span class="token operator">></span>inq_timer_ent<span class="token punctuation">,</span> BTU_TTYPE_BLE_INQUIRY<span class="token punctuation">,</span> duration<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
btm_ble_start_inquiry主要做了三件事:
1)设置扫描参数: btm_update_scanner_filter_policy(SP_ADV_ALL)
2)启动扫描: btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
3)启动扫描定时器,定时器超时后在btu_task中关闭扫描:btu_start_timer (&p_inq->inq_timer_ent, BTU_TTYPE_BLE_INQUIRY, duration)
下面分别对这三件事进行跟踪:
1) 设置扫描参数
Btm_ble_bgconn.c (external\bluetooth\bluedroid\stack\btm)
void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy) { p_inq->sfp = scan_policy; p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
btsnd_hcic_ble_set_scan_params <span class="token punctuation">(</span>p_inq<span class="token operator">-</span><span class="token operator">></span>scan_type<span class="token punctuation">,</span> <span class="token punctuation">(</span>UINT16<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token operator">!</span>p_inq<span class="token operator">-</span><span class="token operator">></span>scan_interval <span class="token operator">?</span> BTM_BLE_GAP_DISC_SCAN_INT <span class="token operator">:</span> p_inq<span class="token operator">-</span><span class="token operator">></span>scan_interval<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>UINT16<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token operator">!</span>p_inq<span class="token operator">-</span><span class="token operator">></span>scan_window <span class="token operator">?</span> BTM_BLE_GAP_DISC_SCAN_WIN <span class="token operator">:</span> p_inq<span class="token operator">-</span><span class="token operator">></span>scan_window<span class="token punctuation">)</span><span class="token punctuation">,</span> btm_cb<span class="token punctuation">.</span>ble_ctr_cb<span class="token punctuation">.</span>addr_mgnt_cb<span class="token punctuation">.</span>own_addr_type<span class="token punctuation">,</span> scan_policy<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Hciblecmds.c (external\bluetooth\bluedroid\stack\hcic)
BOOLEAN btsnd_hcic_ble_set_scan_params (UINT8 scan_type, UINT16 scan_int, UINT16 scan_win, UINT8 addr_type_own, UINT8 scan_filter_policy) { BT_HDR *p; UINT8 *pp;
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>p <span class="token operator">=</span> <span class="token function">HCI_GET_CMD_BUF</span><span class="token punctuation">(</span>HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">(</span>FALSE<span class="token punctuation">)</span><span class="token punctuation">;</span> pp <span class="token operator">=</span> <span class="token punctuation">(</span>UINT8 <span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span>p <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 指向 data[]</span> p<span class="token operator">-</span><span class="token operator">></span>len <span class="token operator">=</span> HCIC_PREAMBLE_SIZE <span class="token operator">+</span> HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM<span class="token punctuation">;</span> p<span class="token operator">-</span><span class="token operator">></span>offset <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> UINT16_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> HCI_BLE_WRITE_SCAN_PARAMS<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_type<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT16_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_int<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT16_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_win<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> addr_type_own<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_filter_policy<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* 发送hci命令 */</span> btu_hcif_send_cmd <span class="token punctuation">(</span>LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span>TRUE<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
2) 启动扫描
Btm_ble_gap.c (external\bluetooth\bluedroid\stack\btm)
tBTM_STATUS btm_ble_start_scan (UINT8 filter_enable) { tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS status = BTM_CMD_STARTED;
<span class="token comment">/* start scan, disable duplicate filtering */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>btsnd_hcic_ble_set_scan_enable <span class="token punctuation">(</span>BTM_BLE_SCAN_ENABLE<span class="token punctuation">,</span> filter_enable<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> status <span class="token operator">=</span> BTM_NO_RESOURCES<span class="token punctuation">;</span> btm_cb<span class="token punctuation">.</span>ble_ctr_cb<span class="token punctuation">.</span>wl_state <span class="token operator">&</span><span class="token operator">=</span> <span class="token operator">~</span>BTM_BLE_WL_SCAN<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> status<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Hciblecmds.c (external\bluetooth\bluedroid\stack\hcic)
BOOLEAN btsnd_hcic_ble_set_scan_enable (UINT8 scan_enable, UINT8 duplicate) { BT_HDR *p; UINT8 *pp;
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>p <span class="token operator">=</span> <span class="token function">HCI_GET_CMD_BUF</span><span class="token punctuation">(</span>HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">(</span>FALSE<span class="token punctuation">)</span><span class="token punctuation">;</span> pp <span class="token operator">=</span> <span class="token punctuation">(</span>UINT8 <span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span>p <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 指向 data[]</span> p<span class="token operator">-</span><span class="token operator">></span>len <span class="token operator">=</span> HCIC_PREAMBLE_SIZE <span class="token operator">+</span> HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE<span class="token punctuation">;</span> p<span class="token operator">-</span><span class="token operator">></span>offset <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> UINT16_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> HCI_BLE_WRITE_SCAN_ENABLE<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_enable<span class="token punctuation">)</span><span class="token punctuation">;</span> UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> duplicate<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* 发送hci命令 */</span> btu_hcif_send_cmd <span class="token punctuation">(</span>LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span>TRUE<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
3) 启动扫描定时器
void btu_start_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout) { BT_HDR *p_msg; GKI_disable();
<span class="token comment">//如果btu定时器轮询停止,则重新启动计数轮询,轮询周期是1s</span> <span class="token comment">/* if timer list is currently empty, start periodic GKI timer */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">.</span>p_first <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">/* if timer starts on other than BTU task */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">GKI_get_taskid</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> BTU_TASK<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">/* post event to start timer in BTU task */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>p_msg <span class="token operator">=</span> <span class="token punctuation">(</span>BT_HDR <span class="token operator">*</span><span class="token punctuation">)</span><span class="token function">GKI_getbuf</span><span class="token punctuation">(</span>BT_HDR_SIZE<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> p_msg<span class="token operator">-</span><span class="token operator">></span>event <span class="token operator">=</span> BT_EVT_TO_START_TIMER<span class="token punctuation">;</span> GKI_send_msg <span class="token punctuation">(</span>BTU_TASK<span class="token punctuation">,</span> TASK_MBOX_0<span class="token punctuation">,</span> p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">/* Start free running 1 second timer for list management */</span> GKI_start_timer <span class="token punctuation">(</span>TIMER_0<span class="token punctuation">,</span> GKI_SECS_TO_TICKS <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> TRUE<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> GKI_remove_from_timer_list <span class="token punctuation">(</span><span class="token operator">&</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">,</span> p_tle<span class="token punctuation">)</span><span class="token punctuation">;</span> p_tle<span class="token operator">-</span><span class="token operator">></span>event <span class="token operator">=</span> type<span class="token punctuation">;</span> p_tle<span class="token operator">-</span><span class="token operator">></span>ticks <span class="token operator">=</span> timeout<span class="token punctuation">;</span> p_tle<span class="token operator">-</span><span class="token operator">></span>ticks_initial <span class="token operator">=</span> timeout<span class="token punctuation">;</span> <span class="token comment">//将定时器添加到GKI定时器列表</span> GKI_add_to_timer_list <span class="token punctuation">(</span><span class="token operator">&</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">,</span> p_tle<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">GKI_enable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
如果btu task的定时器队列为空,说明当前btu task的计时轮询已经停止,所以要启动btu task的计时轮询,轮询周期是1s。最后将定时器添加到GKI定时器列表。
那么定时器超时在哪里执行? 我们找到了GKI_init函数:
Gki_ulinux.c (external\bluetooth\bluedroid\gki\ulinux)
从下面的代码可以看出定时器到期执行函数为bt_alarm_cb:
void GKI_init(void) { pthread_mutexattr_t attr; tGKI_OS *p_os;
memset <span class="token punctuation">(</span><span class="token operator">&</span>gki_cb<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">gki_buffer_init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">gki_timers_init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">alarm_service_init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTicks <span class="token operator">=</span> <span class="token punctuation">(</span>UINT32<span class="token punctuation">)</span> <span class="token function">times</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">pthread_mutexattr_init</span><span class="token punctuation">(</span><span class="token operator">&</span>attr<span class="token punctuation">)</span><span class="token punctuation">;</span> p_os <span class="token operator">=</span> <span class="token operator">&</span>gki_cb<span class="token punctuation">.</span>os<span class="token punctuation">;</span> <span class="token function">pthread_mutex_init</span><span class="token punctuation">(</span><span class="token operator">&</span>p_os<span class="token operator">-</span><span class="token operator">></span>GKI_mutex<span class="token punctuation">,</span> <span class="token operator">&</span>attr<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">struct</span> sigevent sigevent<span class="token punctuation">;</span> <span class="token function">memset</span><span class="token punctuation">(</span><span class="token operator">&</span>sigevent<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>sigevent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> sigevent<span class="token punctuation">.</span>sigev_notify <span class="token operator">=</span> SIGEV_THREAD<span class="token punctuation">;</span> sigevent<span class="token punctuation">.</span>sigev_notify_function <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">void</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token keyword">union</span> sigval<span class="token punctuation">)</span><span class="token punctuation">)</span>bt_alarm_cb<span class="token punctuation">;</span> sigevent<span class="token punctuation">.</span>sigev_value<span class="token punctuation">.</span>sival_ptr <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">timer_create</span><span class="token punctuation">(</span>CLOCK_REALTIME<span class="token punctuation">,</span> <span class="token operator">&</span>sigevent<span class="token punctuation">,</span> <span class="token operator">&</span>posix_timer<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token function">ALOGE</span><span class="token punctuation">(</span><span class="token string">"%s unable to create POSIX timer: %s"</span><span class="token punctuation">,</span> <span class="token constant">__func__</span><span class="token punctuation">,</span> <span class="token function">strerror</span><span class="token punctuation">(</span>errno<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> timer_created <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span> timer_created <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
/** Callback from Java thread after alarm from AlarmService fires. /
static void bt_alarm_cb(void data)
{
GKI_timer_update(ticks_taken > alarm_service.ticks_scheduled
? ticks_taken : alarm_service.ticks_scheduled);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
Gki_time.c (external\bluetooth\bluedroid\gki\common) 25288 2017/12/14
void GKI_timer_update (INT32 ticks_since_last_update) { UINT8 task_id; long next_expiration;
gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTicks <span class="token operator">+</span><span class="token operator">=</span> ticks_since_last_update<span class="token punctuation">;</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTicksTilExp <span class="token operator">-</span><span class="token operator">=</span> ticks_since_last_update<span class="token punctuation">;</span> <span class="token comment">/* Don't allow timer interrupt nesting */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>timer_nesting<span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>timer_nesting <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> next_expiration <span class="token operator">=</span> GKI_NO_NEW_TMRS_STARTED<span class="token punctuation">;</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSNumOrigTicks <span class="token operator">-</span><span class="token operator">=</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTicksTilExp<span class="token punctuation">;</span> <span class="token function">GKI_disable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Check for OS Task Timers */</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>task_id <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> task_id <span class="token operator"><</span> GKI_MAX_TASKS<span class="token punctuation">;</span> task_id<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSWaitTmr<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">/* If timer is running */</span> <span class="token punctuation">{<!-- --></span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSWaitTmr<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">-</span><span class="token operator">=</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSNumOrigTicks<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSWaitTmr<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">/* Timer Expired */</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSRdyTbl<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">=</span> TASK_READY<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
#if (GKI_NUM_TIMERS > 0)
/* If any timer is running, decrement */
if (gki_cb.com.OSTaskTmr0[task_id] > 0)
{
gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks;
<span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token comment">/* Reload timer and set Timer 0 Expired event mask */</span>
gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">=</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0R<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span><span class="token punctuation">;</span>
GKI_send_event <span class="token punctuation">(</span>task_id<span class="token punctuation">,</span> TIMER_0_EVT_MASK<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/* Check to see if this timer is the next one to expire */</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&&</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator"><</span> next_expiration<span class="token punctuation">)</span>
next_expiration <span class="token operator">=</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span><span class="token punctuation">;</span>
#endif
// 此处省略TIMER_1,TIMER_2,TIMER_3相关处理
}
/* Set the next timer experation value if there is one to start */
if (next_expiration < GKI_NO_NEW_TMRS_STARTED)
{
gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration;
}
else
{
gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0;
}
<span class="token comment">// Set alarm service for next alarm.</span>
<span class="token function">alarm_service_reschedule</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">GKI_enable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>timer_nesting <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
如果OSTaskTmr小于0,表示定时器已经超时,这里调用GKI_send_event发送了一个event出去。
Btu_task.c (external\bluetooth\bluedroid\stack\btu)
BTU_API UINT32 btu_task (UINT32 param) { /* Wait for, and process, events */ for (;;) { event = GKI_wait (0xFFFF, 0);
<span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&</span> TIMER_0_EVT_MASK<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> GKI_update_timer_list <span class="token punctuation">(</span><span class="token operator">&</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">GKI_timer_queue_is_empty</span><span class="token punctuation">(</span><span class="token operator">&</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> TIMER_LIST_ENT <span class="token operator">*</span>p_tle <span class="token operator">=</span> <span class="token function">GKI_timer_getfirst</span><span class="token punctuation">(</span><span class="token operator">&</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>p_tle<span class="token operator">-</span><span class="token operator">></span>ticks <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token function">GKI_remove_from_timer_list</span><span class="token punctuation">(</span><span class="token operator">&</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">,</span> p_tle<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span>p_tle<span class="token operator">-</span><span class="token operator">></span>event<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
case BTU_TTYPE_BLE_INQUIRY:
case BTU_TTYPE_BLE_GAP_LIM_DISC:
case BTU_TTYPE_BLE_GAP_FAST_ADV:
case BTU_TTYPE_BLE_OBSERVE:
btm_ble_timeout(p_tle);
break;
<span class="token keyword">case</span> BTU_TTYPE_ATT_WAIT_FOR_RSP<span class="token operator">:</span>
<span class="token function">gatt_rsp_timeout</span><span class="token punctuation">(</span>p_tle<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
if (event & TIMER_2_EVT_MASK)
{
btu_process_quick_timer_evt();
}
#endif
#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
if (event & TIMER_1_EVT_MASK)
{
bta_sys_timer_update();
}
#endif
<span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&</span> TIMER_3_EVT_MASK<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">BTM_TRACE_API</span><span class="token punctuation">(</span><span class="token string">"Received oneshot timer event complete"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
启动扫描的定时器event类型是BTU_TTYPE_BLE_INQUIRY,btm_ble_timeout被调用,最终调用btm_ble_stop_scan停止扫描。
Btm_ble_gap.c (external\bluetooth\bluedroid\stack\btm)
void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
{
switch (p_tle->event)
{
case BTU_TTYPE_BLE_INQUIRY:
btm_ble_stop_inquiry();
btm_ble_stop_scan(); // 停止扫描
break;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
至此启动扫描的三件事都已跟踪完成,现在我们继续分析。
设置扫描参数和启动扫描最后都是调用btu_hcif_send_cmd发送hci命令,
下面我们就对这个函数进行跟踪。
Btu_hcif.c (external\bluetooth\bluedroid\stack\btu)
/******************************************************************************* ** ** Function btu_hcif_send_cmd ** ** Description This function is called to check if it can send commands ** to the Host Controller. It may be passed the address of ** a packet to send. ** ** Returns void ** *******************************************************************************/ void btu_hcif_send_cmd (UINT8 controller_id, BT_HDR *p_buf) { tHCI_CMD_CB * p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
<span class="token comment">/* If there are already commands in the queue, then enqueue this command */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_xmit_q<span class="token punctuation">.</span>count<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> GKI_enqueue <span class="token punctuation">(</span><span class="token operator">&</span><span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_xmit_q<span class="token punctuation">)</span><span class="token punctuation">,</span> p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span> p_buf <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/* Allow for startup case, where no acks may be received */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>controller_id <span class="token operator">==</span> LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_window <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token punctuation">(</span>btm_cb<span class="token punctuation">.</span>devcb<span class="token punctuation">.</span>state <span class="token operator">==</span> BTM_DEV_STATE_WAIT_RESET_CMPLT<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_window <span class="token operator">=</span> p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_xmit_q<span class="token punctuation">.</span>count <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/* See if we can send anything */</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_window <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>p_buf<span class="token punctuation">)</span> p_buf <span class="token operator">=</span> <span class="token punctuation">(</span>BT_HDR <span class="token operator">*</span><span class="token punctuation">)</span>GKI_dequeue <span class="token punctuation">(</span><span class="token operator">&</span><span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_xmit_q<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token function">btu_hcif_store_cmd</span><span class="token punctuation">(</span>controller_id<span class="token punctuation">,</span> p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span> p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_window<span class="token operator">--</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>controller_id <span class="token operator">==</span> LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token function">HCI_CMD_TO_LOWER</span><span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span> <span class="token function">GKI_freebuf</span><span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> p_buf <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span> GKI_enqueue <span class="token punctuation">(</span><span class="token operator">&</span><span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">></span>cmd_xmit_q<span class="token punctuation">)</span><span class="token punctuation">,</span> p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
查看HCI_CMD_TO_LOWER定义:
/* Sends an HCI command received from the upper stack to the BD/EDR HCI transport. */
#ifndef HCI_CMD_TO_LOWER
#define HCI_CMD_TO_LOWER(p) bte_main_hci_send((BT_HDR *)(p), BT_EVT_TO_LM_HCI_CMD);
#endif
- 1
- 2
- 3
- 4
Bte_main.c (external\bluetooth\bluedroid\main)
void bte_main_hci_send (BT_HDR *p_msg, UINT16 event) { UINT16 sub_event = event & BT_SUB_EVT_MASK; /* local controller ID */
p_msg<span class="token operator">-</span><span class="token operator">></span>event <span class="token operator">=</span> event<span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>sub_event <span class="token operator">==</span> LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">)</span> <span class="token operator">||</span> \ <span class="token punctuation">(</span>sub_event <span class="token operator">==</span> LOCAL_BLE_CONTROLLER_ID<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span>bt_hc_if<span class="token punctuation">)</span> bt_hc_if<span class="token operator">-</span><span class="token operator">></span><span class="token function">transmit_buf</span><span class="token punctuation">(</span><span class="token punctuation">(</span>TRANSAC<span class="token punctuation">)</span>p_msg<span class="token punctuation">,</span> \ <span class="token punctuation">(</span><span class="token keyword">char</span> <span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>p_msg <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> \ p_msg<span class="token operator">-</span><span class="token operator">></span>len<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">else</span> <span class="token function">GKI_freebuf</span><span class="token punctuation">(</span>p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
查看bt_hc_if的赋值:
static void bte_main_in_hw_init(void) { // bt_hci_bdroid.c中的 bluetoothHCLibInterface if ( (bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface()) \ == NULL) { APPL_TRACE_ERROR("!!! Failed to get BtHostControllerInterface !!!"); }
<span class="token function">memset</span><span class="token punctuation">(</span><span class="token operator">&</span>preload_retry_cb<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>bt_preload_retry_cb_t<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Bt_hci_bdroid.c (external/bluetooth/bluedroid/hci/src)
void bthc_tx(HC_BT_HDR *buf) {
pthread_mutex_lock(&hc_cb.worker_thread_lock);
if (hc_cb.worker_thread) {
if (buf)
utils_enqueue(&tx_q, buf); // 将buf放入队列tx_q,给到event_tx处理
// 构造一个work_item_t并放入thread->work_queue,
// worker_thread的线程处理函数run_thread会从thread->work_queue中取出这个item,
// 并调用回调函数event_tx
thread_post(hc_cb.worker_thread, event_tx, NULL);
}
pthread_mutex_unlock(&hc_cb.worker_thread_lock);
}
/** Transmit frame /
static int transmit_buf(TRANSAC transac, UNUSED_ATTR char p_buf, UNUSED_ATTR int len) {
bthc_tx((HC_BT_HDR *)transac);
return BT_HC_STATUS_SUCCESS;
}
static const bt_hc_interface_t bluetoothHCLibInterface = {
sizeof(bt_hc_interface_t),
init,
set_power,
lpm,
preload,
postload,
transmit_buf,
logging,
cleanup,
tx_hc_cmd,
};
const bt_hc_interface_t *bt_hc_get_interface(void)
{
return &bluetoothHCLibInterface;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
下面主要看下实际的发送函数event_tx:
event_tx里面有个while循环,通过utils_getnext从tx_q获取所有消息并保存到sending_msg_que,消息的个数为sending_msg_count。消息取完后跳出while,使用一个for循环取出所有要发送的消息并调用 p_hci_if->send发送出去。
注意: 如果我们已用完控制器的未用HCI命令信用(通常为1),则跳过队列中的所有HCI命令数据包。
static void event_tx(UNUSED_ATTR void *context) { /* * We will go through every packets in the tx queue. * Fine to clear tx_cmd_pkts_pending. */ tx_cmd_pkts_pending = false; HC_BT_HDR *sending_msg_que[64]; size_t sending_msg_count = 0; int sending_hci_cmd_pkts_count = 0; utils_lock(); HC_BT_HDR *p_next_msg = tx_q.p_first; while (p_next_msg && sending_msg_count < ARRAY_SIZE(sending_msg_que)) { // 注意: 如果我们已用完控制器的未用HCI命令信用(通常为1), // 则跳过队列中的所有HCI命令数据包。 if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD) { if (tx_cmd_pkts_pending || (sending_hci_cmd_pkts_count >= num_hci_cmd_pkts)) { tx_cmd_pkts_pending = true; p_next_msg = utils_getnext(p_next_msg); // 取出消息 continue; } sending_hci_cmd_pkts_count++; //增加消息计数sending_msg_count }
HC_BT_HDR <span class="token operator">*</span>p_msg <span class="token operator">=</span> p_next_msg<span class="token punctuation">;</span> p_next_msg <span class="token operator">=</span> <span class="token function">utils_getnext</span><span class="token punctuation">(</span>p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 取出消息</span> <span class="token function">utils_remove_from_queue_unlocked</span><span class="token punctuation">(</span><span class="token operator">&</span>tx_q<span class="token punctuation">,</span> p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//把消息放入sending_msg_que,并增加消息计数sending_msg_count</span> sending_msg_que<span class="token punctuation">[</span>sending_msg_count<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> p_msg<span class="token punctuation">;</span>
}
utils_unlock();
for(size_t i = 0; i < sending_msg_count; i++)
p_hci_if->send(sending_msg_que[i]);
if (tx_cmd_pkts_pending)
BTHCDBG(“Used up Tx Cmd credits”);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
p_hci_if在init函数中被赋值:
static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
extern tHCI_IF hci_mct_func_table;
p_hci_if = &hci_h4_func_table
- 1
- 2
- 3
Hci_h4.c (external\bluetooth\bluedroid\hci\src)
/******************************************************************************
** HCI H4 Services interface table
******************************************************************************/
const tHCI_IF hci_h4_func_table =
{
hci_h4_init,
hci_h4_cleanup,
hci_h4_send_msg,
hci_h4_send_int_cmd,
hci_h4_get_acl_data_length,
hci_h4_receive_msg
};
/*******************************************************************************
** Function hci_h4_send_msg
** Description Determine message type, set HCI H4 packet indicator, and
** send message through USERIAL driver
****************************************************************************/
void hci_h4_send_msg(HC_BT_HDR p_msg)
{
uint8_t type = 0;
uint16_t handle;
uint16_t bytes_to_send, lay_spec;
uint8_t p = ((uint8_t )(p_msg + 1)) + p_msg->offset;
uint16_t event = p_msg->event & MSG_EVT_MASK;//event类型
uint16_t sub_event = p_msg->event & MSG_SUB_EVT_MASK; // sub_event类型
uint16_t acl_pkt_size = 0, acl_data_size = 0;
uint16_t bytes_sent;
<span class="token comment">/* wake up BT device if its in sleep mode */</span>
<span class="token function">lpm_wake_assert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">==</span> MSG_STACK_TO_HC_HCI_ACL<span class="token punctuation">)</span>
type <span class="token operator">=</span> H4_TYPE_ACL_DATA<span class="token punctuation">;</span>
<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">==</span> MSG_STACK_TO_HC_HCI_SCO<span class="token punctuation">)</span>
type <span class="token operator">=</span> H4_TYPE_SCO_DATA<span class="token punctuation">;</span>
<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">==</span> MSG_STACK_TO_HC_HCI_CMD<span class="token punctuation">)</span>
type <span class="token operator">=</span> H4_TYPE_COMMAND<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>sub_event <span class="token operator">==</span> LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
acl_data_size <span class="token operator">=</span> h4_cb<span class="token punctuation">.</span>hc_acl_data_size<span class="token punctuation">;</span>
acl_pkt_size <span class="token operator">=</span> h4_cb<span class="token punctuation">.</span>hc_acl_data_size <span class="token operator">+</span> HCI_ACL_PREAMBLE_SIZE<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span>
<span class="token punctuation">{<!-- --></span>
acl_data_size <span class="token operator">=</span> h4_cb<span class="token punctuation">.</span>hc_ble_acl_data_size<span class="token punctuation">;</span>
acl_pkt_size <span class="token operator">=</span> h4_cb<span class="token punctuation">.</span>hc_ble_acl_data_size <span class="token operator">+</span> HCI_ACL_PREAMBLE_SIZE<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* Do all the first chunks */</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>p_msg<span class="token operator">-</span><span class="token operator">></span>len <span class="token operator">></span> acl_pkt_size<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token comment">/* Check if sending ACL data that needs fragmenting */</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>event <span class="token operator">==</span> MSG_STACK_TO_HC_HCI_ACL<span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token punctuation">(</span>p_msg<span class="token operator">-</span><span class="token operator">></span>len <span class="token operator">></span> acl_pkt_size<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
bytes_to_send <span class="token operator">=</span> acl_pkt_size <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token comment">/* 通过uart发送命令/数据 */</span>
bytes_sent <span class="token operator">=</span> <span class="token function">userial_write</span><span class="token punctuation">(</span>event<span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">uint8_t</span> <span class="token operator">*</span><span class="token punctuation">)</span> p<span class="token punctuation">,</span>bytes_to_send<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">write</span><span class="token punctuation">(</span>userial_cb<span class="token punctuation">.</span>fd<span class="token punctuation">,</span> p_data <span class="token operator">+</span> total<span class="token punctuation">,</span> len<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/* 生成btsnoop追踪消息 */</span>
<span class="token function">btsnoop_capture</span><span class="token punctuation">(</span>p_msg<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
p <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">uint8_t</span> <span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span>p_msg <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">+</span> p_msg<span class="token operator">-</span><span class="token operator">></span>offset <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token operator">*</span>p <span class="token operator">=</span> type<span class="token punctuation">;</span>
bytes_to_send <span class="token operator">=</span> p_msg<span class="token operator">-</span><span class="token operator">></span>len <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token comment">/* 通过uart发送命令/数据 */</span>
bytes_sent <span class="token operator">=</span> <span class="token function">userial_write</span><span class="token punctuation">(</span>event<span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">uint8_t</span> <span class="token operator">*</span><span class="token punctuation">)</span> p<span class="token punctuation">,</span> bytes_to_send<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">write</span><span class="token punctuation">(</span>userial_cb<span class="token punctuation">.</span>fd<span class="token punctuation">,</span> p_data <span class="token operator">+</span> total<span class="token punctuation">,</span> len<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/* 生成btsnoop追踪消息 */</span>
<span class="token function">btsnoop_capture</span><span class="token punctuation">(</span>p_msg<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>bt_hc_cbacks<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token comment">// 回调bte_main.c中的hc_cbacks->tx_result</span>
bt_hc_cbacks<span class="token operator">-</span><span class="token operator">></span><span class="token function">tx_result</span><span class="token punctuation">(</span><span class="token punctuation">(</span>TRANSAC<span class="token punctuation">)</span> p_msg<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">char</span> <span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>p_msg <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> \
BT_HC_TX_SUCCESS<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
hci_h4_send_msg主要以下工作:
1)根据消息的event得到event和sub_event
2)根据event得到hci类型,根据sub_event得到acl_data_size和acl_packet_size
3)通过uart发送消息
4)生成btsnoop追踪数据
5)回调uart写成功状态,实际命令发送状态由userial_read_thread来完成。
Userial.c (external\bluetooth\bluedroid\hci\src)
uint16_t userial_write(uint16_t msg_id, const uint8_t *p_data, uint16_t len) { UNUSED(msg_id); uint16_t total = 0; while (len) { ssize_t ret = write(userial_cb.fd, p_data + total, len); switch (ret) { case -1: ALOGE("%s error writing to serial port: %s", __func__, strerror(errno)); return total; case 0: // don't loop forever in case write returns 0. return total; default: total += ret; len -= ret; break; } send_byte_total+=total; }
<span class="token keyword">return</span> total<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
查看userial_cb.fd的赋值:
bool userial_open(userial_port_t port) {
// Call in to the vendor-specific library to open the serial port.
int fd_array[CH_MAX];
int num_ports = vendor_send_command(BT_VND_OP_USERIAL_OPEN, &fd_array);
userial_cb.fd = fd_array[0];
userial_cb.port = port;
if (pthread_create(&userial_cb.read_thread, NULL, userial_read_thread, NULL)) {
ALOGE("%s unable to spawn read thread.", __func__);
goto error;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Vendor.c (external\bluetooth\bluedroid\hci\src)
int vendor_send_command(bt_vendor_opcode_t opcode, void *param) {
return vendor_interface->op(opcode, param);
}
- 1
- 2
- 3
VENDOR_LIBRARY_NAME = "libbt-vendor.so";
vendor_open(const uint8_t *local_bdaddr)
lib_handle = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
vendor_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME);
- 1
- 2
- 3
- 4
dlsym根据动态链接库操作句柄与符号,返回符号对应的地址。
可以得到vendor_interface的实现代码在libbt-vendor.so这个动态链接库中。
Bt_vendor_brcm.c (hardware\broadcom\libbt\src)
全局抓取一下libbt-vendor.so,我们在hardware\broadcom\libbt下的Android.mk中找到了libbt-vendor.so的包含的源文件。
抓取一下bt_vendor_interface_t,发现在Bt_vendor_brcm.c找到了它的实现:
// Entry point of DLib const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = { sizeof(bt_vendor_interface_t), init, op, case BT_VND_OP_USERIAL_OPEN: int (*fd_array)[] = (int (*)[]) param; int fd, idx; fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg); /* Device port name where Bluetooth controller attached */ #ifndef BLUETOOTH_UART_DEVICE_PORT // bt_vendor_brcm.h #define BLUETOOTH_UART_DEVICE_PORT "/dev/ttyO1" // maguro #endif // void userial_vendor_init中赋值: // snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", BLUETOOTH_UART_DEVICE_PORT); vnd_userial.fd = open(vnd_userial.port_name, O_RDWR);//userial_vendor.c return vnd_userial.fd; if (fd != -1) { for (idx=0; idx < CH_MAX; idx++) (*fd_array)[idx] = fd;
retval <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> cleanup
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
再回到hci_h4_send_msg查看bt_hc_cbacks的赋值:
Bt_hci_bdroid.c (external\bluetooth\bluedroid\hci\src)
static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
/* store reference to user callbacks */
bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
static const bt_hc_interface_t bluetoothHCLibInterface = {
sizeof(bt_hc_interface_t),
init,
set_power,
lpm,
preload,
postload,
transmit_buf,
logging,
cleanup,
tx_hc_cmd,
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
bluetoothHCLibInterface的init函数在蓝牙enable的时候被调用:
Bte_main.c (external\bluetooth\bluedroid\main)
bt_hc_callbacks_t *bt_hc_cbacks = NULL;
static const bt_hc_callbacks_t hc_callbacks = {
sizeof(bt_hc_callbacks_t),
preload_cb,
postload_cb,
lpm_cb,
hostwake_ind,
alloc,
dealloc,
data_ind,
tx_result
};
static void bte_main_in_hw_init(void)
{
bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface() // Bt_hci_bdroid.c
return &bluetoothHCLibInterface;
}
bte_main_enable
bte_hci_enable
//调用bluetoothHCLibInterface的init函数,将bt_hc_cbacks赋值为hc_callbacks
int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);
bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb; // Bt_hci_bdroid.c
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
最终将bt_hc_cbacks赋值为hc_callbacks。
二、APK scan
apk scan发生在蓝牙打开以后,分为经典蓝牙扫描和BLE扫描。
1)经典蓝牙扫描
private BluetoothAdapter mBluetoothAdapter;
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// 启动扫描
mBluetoothAdapter.startDiscovery();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
剩下的内容和settings里面开启扫描流程相同。
扫描到的设备在JniCallbacks.java的deviceFoundCallback方法通过广播发送出来。
JniCallbacks.java (packages\apps\bluetooth\src\com\android\bluetooth\btservice)
void deviceFoundCallback(byte[] address)
mRemoteDevices.deviceFoundCallback(address);
// The device properties are already registered - we can send the intent
BluetoothDevice device = getDevice(address); // RemoteDevices.java
DeviceProperties deviceProp = getDeviceProperties(device);
Intent intent = new Intent(BluetoothDevice.ACTION_FOUND);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_CLASS,
new BluetoothClass(Integer.valueOf(deviceProp.mBluetoothClass)));
intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi);
intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName);
mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
应用广播接收代码:
// Broadcast Register private SingBroadcastReceiver mReceiver; mReceiver = new SingBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intentFilter.addAction(BluetoothDevice.ACTION_FOUND); registerReceiver(mReceiver, intentFilter);
<span class="token comment">// Broadcast Receiver</span> <span class="token keyword">class</span> <span class="token class-name">SingBroadcastReceiver</span> <span class="token keyword">extends</span> <span class="token class-name">BroadcastReceiver</span> <span class="token punctuation">{<!-- --></span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onReceive</span><span class="token punctuation">(</span>Context context<span class="token punctuation">,</span> Intent intent<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> String action <span class="token operator">=</span> intent<span class="token punctuation">.</span><span class="token function">getAction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_FOUND<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>action<span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> BluetoothDevice device <span class="token operator">=</span> intent<span class="token punctuation">.</span><span class="token function">getParcelableExtra</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>EXTRA_DEVICE<span class="token punctuation">)</span><span class="token punctuation">;</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string">"MainActivity"</span><span class="token punctuation">,</span> <span class="token string">""</span> <span class="token operator">+</span> device<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">" "</span> <span class="token operator">+</span> device<span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_DISCOVERY_STARTED<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>action<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string">"MainActivity"</span><span class="token punctuation">,</span> <span class="token string">"Discovery started."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_DISCOVERY_FINISHED<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>action<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string">"MainActivity"</span><span class="token punctuation">,</span> <span class="token string">"Discovery finished."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
2)BLE扫描
private BluetoothAdapter mBluetoothAdapter;
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
Log.i(TAG, "mLeScanCallback device: " + device.getName() + " "+ device.getAddress());
}
};
// 启动扫描
mBluetoothAdapter.startLeScan(mLeScanCallback);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
BluetoothAdapter.java (frameworks\base\core\java\android\bluetooth)
/** * Starts a scan for Bluetooth LE devices. * @param callback the callback LE scan results are delivered */ @Deprecated public boolean startLeScan(LeScanCallback callback) { return startLeScan(null, callback); }
<span class="token comment">/** * Starts a scan for Bluetooth LE devices, looking for devices that * advertise given services. * @param serviceUuids Array of services to look for * @param callback the callback LE scan results are delivered */</span> <span class="token annotation punctuation">@Deprecated</span> <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">startLeScan</span><span class="token punctuation">(</span><span class="token keyword">final</span> UUID<span class="token punctuation">[</span><span class="token punctuation">]</span> serviceUuids<span class="token punctuation">,</span> <span class="token keyword">final</span> LeScanCallback callback<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span>DBG<span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">d</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"startLeScan(): "</span> <span class="token operator">+</span> serviceUuids<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>callback <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span>DBG<span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">e</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"startLeScan: null callback"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 获得一个BluetoothLeScanner 对象</span> BluetoothLeScanner scanner <span class="token operator">=</span> <span class="token function">getBluetoothLeScanner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>scanner <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span>DBG<span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">e</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"startLeScan: cannot get BluetoothLeScanner"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 判断mLeScanClients里面是否已有当前扫描的callback,有则表示扫描已开始</span> <span class="token keyword">synchronized</span><span class="token punctuation">(</span>mLeScanClients<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span>mLeScanClients<span class="token punctuation">.</span><span class="token function">containsKey</span><span class="token punctuation">(</span>callback<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span>DBG<span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">e</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"LE Scan has already started"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//获取BluetoothGatt Binder类的实例,该类的定义在GattService.java中</span> <span class="token comment">//GattService内部类private static class BluetoothGattBinder extends IBluetoothGatt.Stub</span> IBluetoothGatt iGatt <span class="token operator">=</span> mManagerService<span class="token punctuation">.</span><span class="token function">getBluetoothGatt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>iGatt <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">// BLE is not supported</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 扫描回调</span> ScanCallback scanCallback <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ScanCallback</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onScanResult</span><span class="token punctuation">(</span><span class="token keyword">int</span> callbackType<span class="token punctuation">,</span> ScanResult result<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>