赞
踩
微信扫码,给个关注吧
昨天梳理了蓝牙的开启流程,今天梳理一遍扫描流程:
/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
void enableScanning() {
// Clear all device states before first scan
if (!mInitialScanStarted) {
if (mAvailableDevicesCategory != null) {
removeAllDevices();
}
mLocalManager.getCachedDeviceManager().clearNonBondedDevices();
mInitialScanStarted = true;
}
super.enableScanning();
}
在这里如果没有开始扫描就清除缓存中所有的设备,然后将缓存的设备中没有配对的设备清除,最后调用了父类 DeviceListPreferenceFragment 的enableScanning()方法:
/packages/apps/Settings/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
void enableScanning() {
// LocalBluetoothAdapter already handles repeated scan requests
mLocalAdapter.startScanning(true);
mScanEnabled = true;
}
这里其实最终调用了/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter的startScanning方法开始扫描。
/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
LocalBluetoothAdapter的startScanning方法:
public 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()) { mLastScan = System.currentTimeMillis(); } } }
/frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
这里最后调用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(); } } 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 中的 startDiscovery 方法:
/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
boolean setDiscoverableTimeout(int timeout) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mAdapterProperties.setDiscoverableTimeout(timeout);
}
这里最终调用tartDiscoveryNative()方法,从 Java 层调到 JNI 层的com_android_bluetooth_btservice_AdapterService.cpp文件中的 startDiscoveryNative 方法:
private native boolean startDiscoveryNative();
int ret = sBluetoothInterface->start_discovery() 这行代码调进了hal层的蓝牙协议栈中。
/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
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
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 用于设备管理相关的功能。
/system/bt/btif/src/btif_dm.cc
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_bta_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_bta_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; }
btif_dm_start_discovery方法中最终调用 /system/bt/bta/dm/bta_dm_api.cc中的 BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
/system/bt/bta/dm/bta_dm_api.cc
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里面:
/system/bt/bta/dm/bta_dm_act.cc
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方法:
/system/bt/bta/dm/bta_dm_act.cc
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); /* 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); 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); } }
之前调用了在/system/bt/bta/dm/bta_dm_act.cc里面的bta_dm_search_start方法时,关键代码是:
result.status = BTM_StartInquiry((tBTM_INQ_PARMS*)&p_data->search.inq_params,
bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb);
这里可以看到在调用btm的开始扫描方法的时候会传入三个参数,第一个就是启动扫描所需要传下去的参数,第二个bta_dm_inq_results_cb就是扫描结果的回调,第三个bta_dm_inq_cmpl_cb就是扫描完成的回调。也就是说btm启动扫描之后,扫描到蓝牙设备之后会通过bta_dm_inq_results_cb这个回调返给bta,而扫描结束之后会通过bta_dm_inq_cmpl_cb这个回调返给bta。
这里我们拿bta_dm_inq_results_cb这个回调来分析:
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; } }
这里面把扫描到的device数据放入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方法:
/system/bt/btif/src/btif_dm.cc
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_search_devices_evt方法就是扫描任务的回调函数,当扫描到设备时,回调这个方法,将上下文从BTE切换到BTIF
再调用btif_dm_search_devices_evt,将扫描到的设备通过HAL_CBACK方式返回。
/system/bt/btif/src/btif_dm.cc
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; case BTA_DM_INQ_RES_EVT: { /* inquiry result */ bt_bdname_t bdname; uint8_t remote_name_len; tBTA_SERVICE_MASK services = 0; p_search_data = (tBTA_DM_SEARCH*)p_param; RawAddress& bdaddr = p_search_data->inq_res.bd_addr; BTIF_TRACE_DEBUG("%s() %s device_type = 0x%x\n", __func__, bdaddr.ToString().c_str(), p_search_data->inq_res.device_type); bdname.name[0] = 0; 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, p_search_data->inq_res.eir_len, &services); BTIF_TRACE_DEBUG("%s()EIR BTA services = %08X", __func__, (uint32_t)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; uint32_t num_properties = 0; bt_status_t status; int addr_type = 0; memset(properties, 0, sizeof(properties)); /* RawAddress */ 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 */ if (bdname.name[0]) { BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_BDNAME, strlen((char*)bdname.name), &bdname); num_properties++; } /* DEV_CLASS */ uint32_t cod = devclass2uint(p_search_data->inq_res.dev_class); BTIF_TRACE_DEBUG("%s cod is 0x%06x", __func__, cod); if (cod != 0) { BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod); num_properties++; } int stored_device_type = 0; if (btif_get_device_type(bdaddr, &stored_device_type) && ((stored_device_type != BT_DEVICE_TYPE_BREDR && p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BREDR) || (stored_device_type != BT_DEVICE_TYPE_BLE && p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE))) { dev_type = (bt_device_type_t)BT_DEVICE_TYPE_DUMO; } else { dev_type = (bt_device_type_t)p_search_data->inq_res.device_type; } if (p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE) addr_type = p_search_data->inq_res.ble_addr_type; 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); status = btif_storage_set_remote_addr_type(&bdaddr, addr_type); ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote addr type (inquiry)", status); /* 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: { do_in_bta_thread( FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0, nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0))); } 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 (!btif_dm_inquiry_in_progress) { btgatt_filt_param_setup_t adv_filt_param; memset(&adv_filt_param, 0, sizeof(btgatt_filt_param_setup_t)); do_in_bta_thread( FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0, nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0))); HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STOPPED); } } break; } }
扫描到设备时,调用的是HAL_CBACK(bt_hal_cbacks, device_found_cb,num_properties, properties);
device_found_cb即是device_found_callback方法,在com_android_bluetooth_btservice_AdapterService.cpp中实现
/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,即
/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
method_deviceFoundCallback =
env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
对应JniCallbacks.java的deviceFoundCallback方法。
/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/JniCallbacks.java
void devicePropertyChangedCallback(byte[] address, int[] types, byte[][] val) {
mRemoteDevices.devicePropertyChangedCallback(address, types, val);
}
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); sAdapterService.sendBroadcastMultiplePermissions(intent, new String[]{ AdapterService.BLUETOOTH_PERM, android.Manifest.permission.ACCESS_COARSE_LOCATION }); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。