安卓蓝牙扫描流程
目录
系统广播
流程图
源码跟踪
系统广播
扫描开启广播:BluetoothAdapter.ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
扫描关闭广播:BluetoothAdapter.ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
扫描结果广播:BluetoothAdapter.ACTION_FOUND = "android.bluetooth.device.action.FOUND";
流程图
安卓系统中应用Application通过蓝牙适配器接口BluetoothAdapter.startDiscovery()的调用触发搜索流程的开始,从这里开始流程分析。
源码跟踪
frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java中调用 startDiscovery
public boolean startDiscovery() {
if (getState() != STATE_ON) {
return false;
}
try {
mServiceLock.readLock().lock();
if (mService != null) {
return mService.startDiscovery(getOpPackageName(), getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
} finally {
mServiceLock.readLock().unlock();
}
return false;
}
这里的Service.startDiscovery属于aidl跨进程通信,通过IBluetooth.aidl调用远程服务中packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java中的startDiscovery
boolean startDiscovery(String callingPackage, @Nullable String callingFeatureId) {
UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId());
debugLog("startDiscovery");
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
boolean isQApp = Utils.isQApp(this, callingPackage);
String permission = null;
if (Utils.checkCallerHasNetworkSettingsPermission(this)) {
permission = android.Manifest.permission.NETWORK_SETTINGS;
} else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) {
permission = android.Manifest.permission.NETWORK_SETUP_WIZARD;
} else if (isQApp) {
if (!Utils.checkCallerHasFineLocation(this, mAppOps, callingPackage, callingFeatureId,
callingUser)) {
return false;
}
permission = android.Manifest.permission.ACCESS_FINE_LOCATION;
} else {
if (!Utils.checkCallerHasCoarseLocation(this, mAppOps, callingPackage, callingFeatureId,
callingUser)) {
return false;
}
permission = android.Manifest.permission.ACCESS_COARSE_LOCATION;
}
synchronized (mDiscoveringPackages) {
mDiscoveringPackages.add(new DiscoveringPackage(callingPackage, permission));
}
return startDiscoveryNative();
}
调用packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp中的startDiscoveryNative
static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
ALOGV("%s", __func__);
if (!sBluetoothInterface) return JNI_FALSE;
int ret = sBluetoothInterface->start_discovery();
return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
调到system\bt\btif\src\bluetooth.cc中的start_discovery
static int start_discovery(void) {
/* sanity check */完整性检查
if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_start_discovery();
}
start_discovery调到system\bt\btif\src\btif_dm.cc中的btif_dm_start_discovery;btif_dm.cc用于设备管理相关功能
/*******************************************************************************
*
* Function btif_dm_start_discovery
*
* Description Start device discovery/inquiry
*
* Returns bt_status_t
*
******************************************************************************/
bt_status_t btif_dm_start_discovery(void) {
tBTA_DM_INQ inq_params;
tBTA_SERVICE_MASK services = 0;
BTIF_TRACE_EVENT("%s", __func__);
/* Cleanup anything remaining on index 0 */
do_in_main_thread(
FROM_HERE,
base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
auto adv_filt_param = std::make_unique<btgatt_filt_param_setup_t>();
/* Add an allow-all filter on index 0*/
adv_filt_param->dely_mode = IMMEDIATE_DELY_MODE;
adv_filt_param->feat_seln = ALLOW_ALL_FILTER;
adv_filt_param->filt_logic_type = BTA_DM_BLE_PF_FILT_LOGIC_OR;
adv_filt_param->list_logic_type = BTA_DM_BLE_PF_LIST_LOGIC_OR;
adv_filt_param->rssi_low_thres = LOWEST_RSSI_VALUE;
adv_filt_param->rssi_high_thres = LOWEST_RSSI_VALUE;
do_in_main_thread(
FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_ADD,
0, base::Passed(&adv_filt_param),
base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
/* TODO: Do we need to handle multiple inquiries at the same time? */
/* Set inquiry params and call API */
inq_params.mode = BTA_DM_GENERAL_INQUIRY | BTA_BLE_GENERAL_INQUIRY;
inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION;
inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;
inq_params.report_dup = true;
inq_params.filter_type = BTA_DM_INQ_CLR;
/* TODO: Filter device by BDA needs to be implemented here */
/* Will be enabled to true once inquiry busy level has been received */
btif_dm_inquiry_in_progress = false;
/* find nearby devices */
BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
return BT_STATUS_SUCCESS;
}
再调到system\bt\bta\dm\bta_dm_api.cc中的BTA_DmSearch
/*******************************************************************************
*
* Function BTA_DmSearch
*
* Description This function searches for peer Bluetooth devices. It
* performs an inquiry and gets the remote name for devices.
* Service discovery is done if services is non zero
*
*
* Returns void
*
******************************************************************************/
void BTA_DmSearch(tBTA_DM_INQ* p_dm_inq, tBTA_SERVICE_MASK services,
tBTA_DM_SEARCH_CBACK* p_cback) {
tBTA_DM_API_SEARCH* p_msg =
(tBTA_DM_API_SEARCH*)osi_calloc(sizeof(tBTA_DM_API_SEARCH));
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);//发送到另一个线程
}
调用bta_sys_sendmsg向BTA发送扫描任务消息。bta_sys_sendmsg是蓝牙协议栈的进程间收发消息机制,比较复杂。通过搜索event标记BTA_DM_API_SEARCH_EVT可以找到system\bt\bta\dm\bta_dm_act.cc中bta_dm_rs_cback
/*******************************************************************************
*
* Function bta_dm_rs_cback
*
* Description Receives the role switch complete event
*
* Returns
*
******************************************************************************/
static void bta_dm_rs_cback(UNUSED_ATTR void* p1) {
APPL_TRACE_WARNING("bta_dm_rs_cback:%d", bta_dm_cb.rs_event);
if (bta_dm_cb.rs_event == BTA_DM_API_SEARCH_EVT) {
bta_dm_cb.search_msg.rs_res =
BTA_DM_RS_OK; /* do not care about the result for now */
bta_dm_cb.rs_event = 0;
bta_dm_search_start((tBTA_DM_MSG*)&bta_dm_cb.search_msg);//调用内部的开启扫描方法
}
}
这里判断如果event是BTA_DM_API_SEARCH_EVT就调用bta本身的bta_dm_search_start方法
/*******************************************************************************
*
* Function bta_dm_search_start
*
* Description Starts an inquiry
*
*
* Returns void
*
******************************************************************************/
void bta_dm_search_start(tBTA_DM_MSG* p_data) {
tBTM_INQUIRY_CMPL result = {};
size_t len = sizeof(Uuid) * p_data->search.num_uuid;
bta_dm_gattc_register();
APPL_TRACE_DEBUG("%s avoid_scatter=%d", __func__,
p_bta_dm_cfg->avoid_scatter);
if (p_bta_dm_cfg->avoid_scatter &&
(p_data->search.rs_res == BTA_DM_RS_NONE) &&
bta_dm_check_av(BTA_DM_API_SEARCH_EVT)) {
LOG(INFO) << __func__ << ": delay search to avoid scatter";
memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH));
return;
}
BTM_ClearInqDb(nullptr); //清楚BTM中之前保存的搜索数据
/* save search params */
bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
bta_dm_search_cb.services = p_data->search.services;
osi_free_and_reset((void**)&bta_dm_search_cb.p_srvc_uuid);
if ((bta_dm_search_cb.num_uuid = p_data->search.num_uuid) != 0 &&
p_data->search.p_uuid != nullptr) {
bta_dm_search_cb.p_srvc_uuid = (Uuid*)osi_malloc(len);
*bta_dm_search_cb.p_srvc_uuid = *p_data->search.p_uuid;
}
result.status = BTM_StartInquiry((tBTM_INQ_PARMS*)&p_data->search.inq_params,
bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb);//调用btm中的启动扫描
APPL_TRACE_EVENT("%s status=%d", __func__, result.status);
if (result.status != BTM_CMD_STARTED) {
LOG(ERROR) << __func__ << ": BTM_StartInquiry returned "
<< std::to_string(result.status);
result.num_resp = 0;
bta_dm_inq_cmpl_cb((void*)&result);
}
}
这里主要就是先清楚BTM中之前的搜索数据,然后保存搜索的参数,调用btm中BTM_StartInquiry方法进行扫描。btm中的扫描在system\bt\stack\btm\btm_inq.cc里
/*******************************************************************************
*
* Function BTM_StartInquiry
*
* Description This function is called to start an inquiry.
*
* Parameters: p_inqparms - pointer to the inquiry information
* mode - GENERAL or LIMITED inquiry, BR/LE bit mask
* seperately
* duration - length in 1.28 sec intervals (If '0', the
* inquiry is CANCELLED)
* max_resps - maximum amount of devices to search for
* before ending the inquiry
* filter_cond_type - BTM_CLR_INQUIRY_FILTER,
* BTM_FILTER_COND_DEVICE_CLASS, or
* BTM_FILTER_COND_BD_ADDR
* filter_cond - value for the filter (based on
* filter_cond_type)
*
* p_results_cb - Pointer to the callback routine which gets
* called upon receipt of an inquiry result. If
* this field is NULL, the application is not
* notified.
*
* p_cmpl_cb - Pointer to the callback routine which gets
* called upon completion. If this field is
* NULL, the application is not notified when
* completed.
* Returns tBTM_STATUS
* BTM_CMD_STARTED if successfully initiated
* BTM_BUSY if already in progress
* BTM_ILLEGAL_VALUE if parameter(s) are out of range
* BTM_NO_RESOURCES if could not allocate resources to start
* the command
* BTM_WRONG_MODE if the device is not up.
*
******************************************************************************/
tBTM_STATUS BTM_StartInquiry(tBTM_INQ_PARMS* p_inqparms,
tBTM_INQ_RESULTS_CB* p_results_cb,
tBTM_CMPL_CB* p_cmpl_cb) {
tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
if (bluetooth::shim::is_gd_shim_enabled()) {
return bluetooth::shim::BTM_StartInquiry(p_inqparms, p_results_cb,
p_cmpl_cb);
}
BTM_TRACE_API("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
p_inqparms->filter_cond_type);
/* Only one active inquiry is allowed in this implementation.
Also do not allow an inquiry if the inquiry filter is being updated */
if (p_inq->inq_active || p_inq->inqfilt_active) {
LOG(ERROR) << __func__ << ": BTM_BUSY";
return (BTM_BUSY);
} else {
p_inq->scan_type = INQ_GENERAL;
}
/*** Make sure the device is ready ***/
if (!BTM_IsDeviceUp()) {
LOG(ERROR) << __func__ << ": adapter is not up";
return BTM_WRONG_MODE;
}
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_GENERAL_INQUIRY &&
(p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_LIMITED_INQUIRY &&
(p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_GENERAL_INQUIRY &&
(p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_LIMITED_INQUIRY) {
LOG(ERROR) << __func__ << ": illegal inquiry mode "
<< std::to_string(p_inqparms->mode);
return (BTM_ILLEGAL_VALUE);
}
/* Save the inquiry parameters to be used upon the completion of
* setting/clearing the inquiry filter */
p_inq->inqparms = *p_inqparms;
/* Initialize the inquiry variables */
p_inq->state = BTM_INQ_ACTIVE_STATE;
p_inq->p_inq_cmpl_cb = p_cmpl_cb;
p_inq->p_inq_results_cb = p_results_cb;
p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
p_inq->inq_active = p_inqparms->mode;
BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x",
p_inq->inq_active);
tBTM_STATUS status = BTM_CMD_STARTED;
/* start LE inquiry here if requested */
if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)) {
if (!controller_get_interface()->supports_ble()) {
LOG(ERROR) << __func__ << ": trying to do LE scan on a non-LE adapter";
p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
status = BTM_ILLEGAL_VALUE;
} else {
/* BLE for now does not support filter condition for inquiry */
status = btm_ble_start_inquiry(
(uint8_t)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
p_inqparms->duration);
if (status != BTM_CMD_STARTED) {
LOG(ERROR) << __func__ << ": Error Starting LE Inquiry";
p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
}
}
p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
}
/* we're done with this routine if BR/EDR inquiry is not desired. */
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE) {
return status;
}
/* BR/EDR inquiry portion */
/* If a filter is specified, then save it for later and clear the current
filter.
The setting of the filter is done upon completion of clearing of the
previous
filter.
*/
switch (p_inqparms->filter_cond_type) {
case BTM_CLR_INQUIRY_FILTER:
p_inq->state = BTM_INQ_SET_FILT_STATE;
break;
case BTM_FILTER_COND_DEVICE_CLASS:
case BTM_FILTER_COND_BD_ADDR:
/* The filter is not being used so simply clear it;
the inquiry can start after this operation */
p_inq->state = BTM_INQ_CLR_FILT_STATE;
p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
/* =============>>>> adding LE filtering here ????? */
break;
default:
LOG(ERROR) << __func__ << ": invalid filter condition type "
<< std::to_string(p_inqparms->filter_cond_type);
return (BTM_ILLEGAL_VALUE);
}
/* Before beginning the inquiry the current filter must be cleared, so
* initiate the command */
status = btm_set_inq_event_filter(p_inqparms->filter_cond_type,
&p_inqparms->filter_cond);
if (status != BTM_CMD_STARTED) {
LOG(ERROR) << __func__ << ": failed to set inquiry event filter";
p_inq->state = BTM_INQ_INACTIVE_STATE;
}
return (status);
}
调用system\bt\stack\btm\btm_ble_gap.cc 中的btm_ble_start_inquiry
/*******************************************************************************
*
* Function btm_ble_start_inquiry
*
* Description This function is called to start BLE inquiry procedure.
* If the duration is zero, the periodic inquiry mode is
* cancelled.
*
* Parameters: mode - GENERAL or LIMITED inquiry
* p_inq_params - pointer to the BLE inquiry parameter.
* p_results_cb - callback returning pointer to results
* (tBTM_INQ_RESULTS)
* p_cmpl_cb - callback indicating the end of an inquiry
*
*
*
* Returns BTM_CMD_STARTED if successfully started
* BTM_NO_RESOURCES if could not allocate a message buffer
* BTM_BUSY - if an inquiry is already active
*
******************************************************************************/
tBTM_STATUS btm_ble_start_inquiry(uint8_t mode, uint8_t duration) {
tBTM_STATUS status = BTM_CMD_STARTED;
tBTM_BLE_CB* p_ble_cb = &btm_cb.ble_ctr_cb;
tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
BTM_TRACE_DEBUG("btm_ble_start_inquiry: mode = %02x inq_active = 0x%02x",
mode, btm_cb.btm_inq_vars.inq_active);
/* if selective connection is active, or inquiry is already active, reject it
*/
if (BTM_BLE_IS_INQ_ACTIVE(p_ble_cb->scan_activity)) {
BTM_TRACE_ERROR("LE Inquiry is active, can not start inquiry");
return (BTM_BUSY);
}
if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) {
btm_send_hci_set_scan_params(
BTM_BLE_SCAN_MODE_ACTI, BTM_BLE_LOW_LATENCY_SCAN_INT,
BTM_BLE_LOW_LATENCY_SCAN_WIN,
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, SP_ADV_ALL);
#if (BLE_PRIVACY_SPT == TRUE)
/* enable IRK list */
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
#endif
p_ble_cb->inq_var.scan_type = BTM_BLE_SCAN_MODE_ACTI;
p_ble_cb->inq_var.scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
status = btm_ble_start_scan();
} else if ((p_ble_cb->inq_var.scan_interval !=
BTM_BLE_LOW_LATENCY_SCAN_INT) ||
(p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) {
BTM_TRACE_DEBUG("%s, restart LE scan with low latency scan params",
__func__);
btm_send_hci_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
btm_send_hci_set_scan_params(
BTM_BLE_SCAN_MODE_ACTI, BTM_BLE_LOW_LATENCY_SCAN_INT,
BTM_BLE_LOW_LATENCY_SCAN_WIN,
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, SP_ADV_ALL);
btm_send_hci_scan_enable(BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE);
}
if (status == BTM_CMD_STARTED) {
p_inq->inq_active |= mode;
p_ble_cb->scan_activity |= mode;
BTM_TRACE_DEBUG("btm_ble_start_inquiry inq_active = 0x%02x",
p_inq->inq_active);
if (duration != 0) {
/* start inquiry timer */
uint64_t duration_ms = duration * 1000;
alarm_set_on_mloop(p_ble_cb->inq_var.inquiry_timer, duration_ms,
btm_ble_inquiry_timer_timeout, NULL);
}
}
return status;
}
再调用btm_send_hci_scan_enable向HCI发送扫描通知
void btm_send_hci_scan_enable(uint8_t enable, uint8_t filter_duplicates) {
if (controller_get_interface()->supports_ble_extended_advertising()) {
btsnd_hcic_ble_set_extended_scan_enable(enable, filter_duplicates, 0x0000,
0x0000);
} else {
btsnd_hcic_ble_set_scan_enable(enable, filter_duplicates);//真正与HCI打交道
}
}
这里判断是否支持ble扩展,则调用system\bt\stack\hcic\hciblecmds.cc中的btsnd_hcic_ble_set_scan_enable
void btsnd_hcic_ble_set_scan_enable(uint8_t scan_enable, uint8_t duplicate) {
BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
uint8_t* pp = (uint8_t*)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE;
p->offset = 0;
UINT16_TO_STREAM(pp, HCI_BLE_WRITE_SCAN_ENABLE);
UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE);
UINT8_TO_STREAM(pp, scan_enable);
UINT8_TO_STREAM(pp, duplicate);
btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);//这里向hci层发命令
}
这里通过和HCI层的通信,host告诉controlor蓝牙地址、数据、命令等,从而控制底层硬件发起配对操作。btu如何与hci通信也比较复杂...
扫描结果返回
主要看下扫描到的设备信息返回。开始扫描和结束扫描的流程见图
之前在调用了system\bt\bta\dm\bta_dm_act.cc中bta_dm_search_start时,传了三个参数,第一个是启动扫描所需传下去的参数,第二个bta_dm_inq_results_cb是扫描结果返回的回调,第三个是扫描完成的回调。
result.status = BTM_StartInquiry((tBTM_INQ_PARMS*)&p_data->search.inq_params,
bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb);//调用btm中的启动扫描
static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, uint8_t* p_eir,
uint16_t eir_len) {
tBTA_DM_SEARCH result;
tBTM_INQ_INFO* p_inq_info;
uint16_t service_class;
result.inq_res.bd_addr = p_inq->remote_bd_addr;
memcpy(result.inq_res.dev_class, p_inq->dev_class, DEV_CLASS_LEN);
BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class);
result.inq_res.is_limited =
(service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false;
result.inq_res.rssi = p_inq->rssi;
result.inq_res.ble_addr_type = p_inq->ble_addr_type;
result.inq_res.inq_result_type = p_inq->inq_result_type;
result.inq_res.device_type = p_inq->device_type;
result.inq_res.flag = p_inq->flag;
/* application will parse EIR to find out remote device name */
result.inq_res.p_eir = p_eir;
result.inq_res.eir_len = eir_len;
p_inq_info = BTM_InqDbRead(p_inq->remote_bd_addr);
if (p_inq_info != NULL) {
/* initialize remt_name_not_required to false so that we get the name by
* default */
result.inq_res.remt_name_not_required = false;
}
if (bta_dm_search_cb.p_search_cback)
bta_dm_search_cb.p_search_cback(BTA_DM_INQ_RES_EVT, &result);
if (p_inq_info) {
/* application indicates if it knows the remote name, inside the callback
copy that to the inquiry data base*/
if (result.inq_res.remt_name_not_required)
p_inq_info->appl_knows_rem_name = true;
}
}
在这里把扫描的devices数据放到result里通过bta_dm_search_cb.p_search_cback(BTA_DM_INQ_RES_EVT, &result);回传。event是BTA_DM_INQ_RES_EVT,通过搜索BTA_DM_INQ_RES_EVT发现在system\bt\btif\src\btif_dm.cc中有一个bte_search_devices_evt方法
static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event,
tBTA_DM_SEARCH* p_data) {
uint16_t param_len = 0;
if (p_data) param_len += sizeof(tBTA_DM_SEARCH);
/* Allocate buffer to hold the pointers (deep copy). The pointers will point
* to the end of the tBTA_DM_SEARCH */
switch (event) {
case BTA_DM_INQ_RES_EVT: {
if (p_data->inq_res.p_eir) param_len += p_data->inq_res.eir_len;
} break;
case BTA_DM_DISC_RES_EVT: {
if (p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data)
param_len += p_data->disc_res.raw_data_size;
} break;
}
BTIF_TRACE_DEBUG("%s event=%s param_len=%d", __func__,
dump_dm_search_event(event), param_len);
/* if remote name is available in EIR, set teh flag so that stack doesnt
* trigger RNR */
if (event == BTA_DM_INQ_RES_EVT)
p_data->inq_res.remt_name_not_required =
check_eir_remote_name(p_data, NULL, NULL);
btif_transfer_context(
btif_dm_search_devices_evt, (uint16_t)event, (char*)p_data, param_len,
(param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL);
}
这里当扫描到设备时,回调这个方法,将上下文从BTE切换到BTIF再调用btif_dm_search_devices_evt,将扫描到的设备通过HAL_CBACK方式返回
/******************************************************************************
*
* Function btif_dm_search_devices_evt
*
* Description Executes search devices callback events in btif context
*
* Returns void
*
*****************************************************************************/
static void btif_dm_search_devices_evt(uint16_t event, char* p_param) {
tBTA_DM_SEARCH* p_search_data;
BTIF_TRACE_EVENT("%s event=%s", __func__, dump_dm_search_event(event));
switch (event) {
case BTA_DM_DISC_RES_EVT: {
p_search_data = (tBTA_DM_SEARCH*)p_param;
/* Remote name update */
if (strlen((const char*)p_search_data->disc_res.bd_name)) {
bt_property_t properties[1];
bt_status_t status;
properties[0].type = BT_PROPERTY_BDNAME;
properties[0].val = p_search_data->disc_res.bd_name;
properties[0].len = strlen((char*)p_search_data->disc_res.bd_name);
RawAddress& bdaddr = p_search_data->disc_res.bd_addr;
status =
btif_storage_set_remote_device_property(&bdaddr, &properties[0]);
ASSERTC(status == BT_STATUS_SUCCESS,
"failed to save remote device property", status);
HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, status, &bdaddr,
1, properties);
}
/* TODO: Services? */
} break;
......省略
}
扫描到设备时,调用HAL_CBACK(bt_hal_cbacks, device_found_cb, num_properties, properties);
device_found_cb是device_found_callback方法,在packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp中实现
static void device_found_callback(int num_properties,
bt_property_t* properties) {
CallbackEnv sCallbackEnv(__func__);
if (!sCallbackEnv.valid()) return;
ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), NULL);
int addr_index;
for (int i = 0; i < num_properties; i++) {
if (properties[i].type == BT_PROPERTY_BDADDR) {
addr.reset(sCallbackEnv->NewByteArray(properties[i].len));
if (!addr.get()) {
ALOGE("Address is NULL (unable to allocate) in %s", __func__);
return;
}
sCallbackEnv->SetByteArrayRegion(addr.get(), 0, properties[i].len,
(jbyte*)properties[i].val);
addr_index = i;
}
}
if (!addr.get()) {
ALOGE("Address is NULL in %s", __func__);
return;
}
ALOGV("%s: Properties: %d, Address: %s", __func__, num_properties,
(const char*)properties[addr_index].val);
remote_device_properties_callback(BT_STATUS_SUCCESS,
(RawAddress*)properties[addr_index].val,
num_properties, properties);
sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback,
addr.get());
}
该方法对应JNI为method_deviceFoundCallback,即
method_deviceFoundCallback =
env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
对应JniCallbacks.java中的deviceFoundCallback方法
deviceFoundCallback再将扫描到的广播发送出去
packages\apps\Bluetooth\src\com\android\bluetooth\btservice\RemoteDevices.java
void deviceFoundCallback(byte[] address) {
// The device properties are already registered - we can send the intent
// now
BluetoothDevice device = getDevice(address);
debugLog("deviceFoundCallback: Remote Address is:" + device);
DeviceProperties deviceProp = getDeviceProperties(device);
if (deviceProp == null) {
errorLog("Device Properties is null for Device:" + device);
return;
}
Intent intent = new Intent(BluetoothDevice.ACTION_FOUND);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_CLASS,
new BluetoothClass(deviceProp.mBluetoothClass));
intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi);
intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName);
final ArrayList<DiscoveringPackage> packages = sAdapterService.getDiscoveringPackages();
synchronized (packages) {
for (DiscoveringPackage pkg : packages) {
intent.setPackage(pkg.getPackageName());
sAdapterService.sendBroadcastMultiplePermissions(intent, new String[]{
AdapterService.BLUETOOTH_PERM, pkg.getPermission()
});
}
}
}