Bluetooth之蓝牙scan 全程分析
来源:互联网 发布:icloud照片怎么导入mac 编辑:程序博客网 时间:2024/05/19 08:05
我们分析的起点是在setting里,从这里跟踪scan 的每个步骤.
Z:\8939_21391\packages\apps\Settings\src\com\android\settings\bluetooth\LocalBluetoothAdapter.java
通过startScanning 进行扫描.
void startScanning(boolean force) { // Only start if we're not already scanning if (!mAdapter.isDiscovering()) { if (!force) { // Don't scan more than frequently than SCAN_EXPIRATION_MS, // unless forced if (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) { return; } // If we are playing music, don't scan unless forced. A2dpProfile a2dp = mProfileManager.getA2dpProfile(); if (a2dp != null && a2dp.isA2dpPlaying()) { return; } A2dpSinkProfile a2dpSink = mProfileManager.getA2dpSinkProfile(); if ((a2dpSink != null) && (a2dpSink.isA2dpPlaying())){ return; } } if (mAdapter.startDiscovery()) { //实际的操作,跳转到framework 继续 mLastScan = System.currentTimeMillis(); } }}
Z:\8939_21391\frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
//framework层的实现,
Z:\8939_21391\frameworks\base\core\java\android\bluetooth\IBluetooth.aidlprivate IBluetooth mService;//借AIDL 调用service继续后续操作.
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;}
Z:\8939_21391\packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
mService 在上面的声明中可以看出. 是IBluetooth类型的,但是实际的IBluetooth.aidl 的实现是在下面.mService就是AIDLService对象, 这就是aidl 进行IPC通信的一个例子,
private static class AdapterServiceBinder extends IBluetooth.Stub{public boolean startDiscovery() { if (!Utils.checkCaller()) { Log.w(TAG, "startDiscovery() - Not allowed for non-active user"); return false; } AdapterService service = getService(); if (service == null) return false; return service.startDiscovery();}}也就是BluetoothAdapter 通过binder 通信调用 AdapterService 实现的IPC方法.AdapterService 实现了进一步的startDiscovery,这里开始进行JNI调用, 然后JNI向下进行HAL层调用.最后到BT的bluedroid层.最后到btif->Bta .
boolean startDiscovery() { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); return startDiscoveryNative();}Z:\8939_21391\packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) { ALOGV("%s:",__FUNCTION__); jboolean result = JNI_FALSE; if (!sBluetoothInterface) return result; int ret = sBluetoothInterface->start_discovery(); result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; return result;} <pre style="background-color: rgb(255, 255, 255);"><span style="font-family: 宋体; font-size: 9pt;"></span>static const bt_interface_t *sBluetoothInterface = NULL;// 这个interface的类型是在HAL层
上面是JNI层的scan 实现了. 接下来我们要进入HAL层然后到stack .
HAL层接口定义在
Z:\8939_21391\hardware\libhardware\include\hardware\bluetooth.h
sBluetoothInterface->start_discovery(); HAL实现是在bluedroid部分. 代码路径和实现代码同样贴出来.
Z:\8939_21391\external\bluetooth\bluedroid\btif\src\bluetooth.c
static int start_discovery(void){ /* sanity check */ if (interface_ready() == FALSE) return BT_STATUS_NOT_READY; return btif_dm_start_discovery();}继续:bt_status_t btif_dm_start_discovery(void){ tBTA_DM_INQ inq_params; tBTA_SERVICE_MASK services = 0; tBTA_DM_BLE_PF_FILT_PARAMS adv_filt_param; BTIF_TRACE_EVENT("%s : pairing_cb.state: 0x%x", __FUNCTION__, pairing_cb.state); /* We should not go for inquiry in BONDING STATE. */ if (pairing_cb.state == BT_BOND_STATE_BONDING) return BT_STATUS_BUSY;#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) memset(&adv_filt_param, 0, sizeof(tBTA_DM_BLE_PF_FILT_PARAMS)); /* Cleanup anything remaining on index 0 */ BTA_DmBleScanFilterSetup(BTA_DM_BLE_SCAN_COND_DELETE, 0, &adv_filt_param, NULL, bte_scan_filt_param_cfg_evt, 0); /* 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; BTA_DmBleScanFilterSetup(BTA_DM_BLE_SCAN_COND_ADD, 0, &adv_filt_param, NULL, 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;#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) inq_params.intl_duration[0]= BTIF_DM_INTERLEAVE_DURATION_BR_ONE; inq_params.intl_duration[1]= BTIF_DM_INTERLEAVE_DURATION_LE_ONE; inq_params.intl_duration[2]= BTIF_DM_INTERLEAVE_DURATION_BR_TWO; inq_params.intl_duration[3]= BTIF_DM_INTERLEAVE_DURATION_LE_TWO;#endif#else inq_params.mode = BTA_DM_GENERAL_INQUIRY;// 进行一般的查找#endif 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;}inq_params 是构造出来的查询条件参数.部分参数解释如下:tBTA_DM_INQ_MODE mode; /* Inquiry mode, limited or general. */ UINT8 duration; /* Inquiry duration in 1.28 sec units. */ UINT8 max_resps; /* Maximum inquiry responses. Set to zero for unlimited responses. */ BOOLEAN report_dup; /* report duplicated inquiry response with higher RSSI value */ tBTA_DM_INQ_FILT filter_type; /* Filter condition type. */ tBTA_DM_INQ_COND filter_cond; /* Filter condition data. */
/* find nearby devices */
BTA_DmSearch(&inq_params, services, bte_search_devices_evt);// 开始搜索附近的BT设备了./*********************************************************************************** Function bte_search_devices_evt**** Description Switches context from BTE to BTIF for DM search events**** Returns void*********************************************************************************/static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data){ UINT16 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 && p_data->inq_res.p_eir) param_len += HCI_EXT_INQ_RESPONSE_LEN; } break; case BTA_DM_DISC_RES_EVT: { if (p_data && 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", __FUNCTION__, dump_dm_search_event(event), param_len); /* if remote name is available in EIR, set teh flag so that stack doesnt trigger RNR */ if (p_data && 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) event, (void *)p_data, param_len, (param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL);}static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data){ UINT16 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 && p_data->inq_res.p_eir) param_len += HCI_EXT_INQ_RESPONSE_LEN; } break; case BTA_DM_DISC_RES_EVT: { if (p_data && 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", __FUNCTION__, dump_dm_search_event(event), param_len); /* if remote name is available in EIR, set teh flag so that stack doesnt trigger RNR */ if (p_data && 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 (<span style="color:#ff0000;">btif_dm_search_devices_evt </span>, (UINT16) event, (void *)p_data, param_len, (param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL);/********************************************************************************** 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 event, char *p_param){ tBTA_DM_SEARCH *p_search_data; BTIF_TRACE_EVENT("%s event=%s", __FUNCTION__, 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_bdaddr_t bdaddr; 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); bdcpy(bdaddr.address, 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; case BTA_DM_INQ_RES_EVT: { /* inquiry result */ UINT32 cod; UINT8 *p_eir_remote_name = NULL; bt_bdname_t bdname; bt_bdaddr_t bdaddr; UINT8 remote_name_len; UINT8 *p_cached_name = NULL; tBTA_SERVICE_MASK services = 0; bdstr_t bdstr; p_search_data = (tBTA_DM_SEARCH *)p_param; bdcpy(bdaddr.address, p_search_data->inq_res.bd_addr); BTIF_TRACE_DEBUG("%s() %s device_type = 0x%x\n", __FUNCTION__, bd2str(&bdaddr, &bdstr),#if (BLE_INCLUDED == TRUE) p_search_data->inq_res.device_type);#else BT_DEVICE_TYPE_BREDR);#endif bdname.name[0] = 0; cod = devclass2uint (p_search_data->inq_res.dev_class); if ( cod == 0) { ALOGD("cod is 0, set as unclassified"); cod = COD_UNCLASSIFIED; } if (!check_eir_remote_name(p_search_data, bdname.name, &remote_name_len)) check_cached_remote_name(p_search_data, bdname.name, &remote_name_len); /* Check EIR for remote name and services */ if (p_search_data->inq_res.p_eir) { BTA_GetEirService(p_search_data->inq_res.p_eir, &services); BTIF_TRACE_DEBUG("%s()EIR BTA services = %08X", __FUNCTION__, (UINT32)services); /* TODO: Get the service list and check to see which uuids we got and send it back to the client. */ } { bt_property_t properties[5]; bt_device_type_t dev_type; UINT8 addr_type; uint32_t num_properties = 0; bt_status_t status; bt_bdname_t alias; memset(&alias, 0, sizeof(alias)); BTIF_DM_GET_REMOTE_PROP(&bdaddr, BT_PROPERTY_REMOTE_FRIENDLY_NAME, &alias, sizeof(alias), properties[num_properties]); memset(properties, 0, sizeof(properties)); /* BD_ADDR */ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_BDADDR, sizeof(bdaddr), &bdaddr); num_properties++; /* BD_NAME */ /* Don't send BDNAME if it is empty */ /* send alias name as the name if alias name present */ if(alias.name[0] != '\0') { BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_BDNAME, strlen((char *)alias.name), &alias); num_properties++; } else if (bdname.name[0]) { if( (check_eir_is_remote_name_short(p_search_data) == TRUE) && (btif_storage_is_device_bonded(&bdaddr) == TRUE) ) { BTIF_TRACE_DEBUG("%s Don't update about the device name ", __FUNCTION__); } else { BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_BDNAME, strlen((char *)bdname.name), &bdname); num_properties++; } } /* DEV_CLASS */ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod); num_properties++; /* DEV_TYPE */#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) /* FixMe: Assumption is that bluetooth.h and BTE enums match */ dev_type = p_search_data->inq_res.device_type; addr_type = p_search_data->inq_res.ble_addr_type;#else dev_type = BT_DEVICE_TYPE_BREDR;#endif BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &dev_type); num_properties++; /* RSSI */ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_REMOTE_RSSI, sizeof(int8_t), &(p_search_data->inq_res.rssi)); num_properties++; status = btif_storage_add_remote_device(&bdaddr, num_properties, properties); ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote device (inquiry)", status);#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) status = btif_storage_set_remote_addr_type(&bdaddr, addr_type); if (( dev_type == BT_DEVICE_TYPE_DUMO)&& (p_search_data->inq_res.flag & BTA_BLE_DMT_CONTROLLER_SPT) && (p_search_data->inq_res.flag & BTA_BLE_DMT_HOST_SPT)) { btif_storage_set_dmt_support_type (&bdaddr, TRUE); } ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote addr type (inquiry)", status);#endif /* Callback to notify upper layer of device */ HAL_CBACK(bt_hal_cbacks, device_found_cb, num_properties, properties); } } break; case BTA_DM_INQ_CMPL_EVT: {#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) tBTA_DM_BLE_PF_FILT_PARAMS adv_filt_param; memset(&adv_filt_param, 0, sizeof(tBTA_DM_BLE_PF_FILT_PARAMS)); BTA_DmBleScanFilterSetup(BTA_DM_BLE_SCAN_COND_DELETE, 0, &adv_filt_param, NULL, bte_scan_filt_param_cfg_evt, 0);#endif } break; case BTA_DM_DISC_CMPL_EVT: { HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STOPPED); } break; case BTA_DM_SEARCH_CANCEL_CMPL_EVT: { /* if inquiry is not in progress and we get a cancel event, then * it means we are done with inquiry, but remote_name fetches are in * progress * * if inquiry is in progress, then we don't want to act on this cancel_cmpl_evt * but instead wait for the cancel_cmpl_evt via the Busy Level * */ if (btif_dm_inquiry_in_progress == FALSE) {#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) tBTA_DM_BLE_PF_FILT_PARAMS adv_filt_param; memset(&adv_filt_param, 0, sizeof(tBTA_DM_BLE_PF_FILT_PARAMS)); BTA_DmBleScanFilterSetup(BTA_DM_BLE_SCAN_COND_DELETE, 0, &adv_filt_param, NULL, bte_scan_filt_param_cfg_evt, 0);#endif HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STOPPED); } } break; }}bta/dm/bta_dm_api.c/*********************************************************************************** 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; if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(sizeof(tBTA_DM_API_SEARCH))) != NULL)// 获取一个tBTA_DM_API_SEARCH 类型的message buff { memset(p_msg, 0, 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;//填充msg bta_sys_sendmsg(p_msg);// 想stack的 }}
Bta_sys_main.c 注释很清晰了,.我就不啰嗦了./*********************************************************************************** Function bta_sys_sendmsg**** Description Send a GKI message to BTA. This function is designed to** optimize sending of messages to BTA. It is called by BTA** API functions and call-in functions.****** Returns void*********************************************************************************/void bta_sys_sendmsg(void *p_msg){ GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);}发送消息到BTA 进程后开始查询工作. 继续追踪.
备注:
1. btif_task BTIF task handler managing all messages being passed Bluetooth HAL and BTA.
0 0
- Bluetooth之蓝牙scan 全程分析
- Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
- Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
- Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
- Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
- Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
- Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
- iOS之蓝牙(Bluetooth)
- 蓝牙之十八- bluetooth pair
- android蓝牙扫描(scan)设备分析
- BlueTooth: 蓝牙协议栈实现模式分析
- BlueTooth: 蓝牙基带数据传输机理分析
- BlueTooth: 蓝牙协议栈实现模式分析
- BlueTooth: 蓝牙协议栈实现模式分析
- BlueTooth:蓝牙协议栈实现模式分析
- BlueTooth: 蓝牙协议栈实现模式分析
- BlueTooth: 蓝牙协议栈实现模式分析
- 蓝牙之十七-bluedroid scan流程
- Sping之Bean的生命周期
- JAVA中int与string互转的效率对比
- Java代理模式
- git生成ssh key及本地解决多个ssh key的问题
- JS 打开新窗口的方法
- Bluetooth之蓝牙scan 全程分析
- 快速学会缓存工具DiskLruCache
- 获取当前年月日和星期
- ZOJ 1008 Gnome Tetravex
- 网站的安全架构
- 用户、角色、权限数据库设计
- PgBouncer简述
- 数据库及实例信息管理
- cs初入 开博