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.aidl
private 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