/****************************************************************************** * * Copyright 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ #define LOG_TAG "bt_btif_scanner" #include #include #include #include #include #include #include #include #include "device/include/controller.h" #include "btif_common.h" #include "btif_util.h" #include "main/shim/le_scanning_manager.h" #include "main/shim/shim.h" #include #include "advertise_data_parser.h" #include "bta_api.h" #include "bta_gatt_api.h" #include "btif_config.h" #include "btif_dm.h" #include "btif_gatt.h" #include "btif_gatt_util.h" #include "btif_storage.h" #include "osi/include/log.h" #include "stack/include/btu.h" #include "vendor_api.h" using base::Bind; using base::Owned; using std::vector; using RegisterCallback = BleScannerInterface::RegisterCallback; extern const btgatt_callbacks_t* bt_gatt_callbacks; #define SCAN_CBACK_IN_JNI(P_CBACK, ...) \ do { \ if (bt_gatt_callbacks && bt_gatt_callbacks->scanner->P_CBACK) { \ BTIF_TRACE_API("HAL bt_gatt_callbacks->client->%s", #P_CBACK); \ do_in_jni_thread( \ Bind(bt_gatt_callbacks->scanner->P_CBACK, __VA_ARGS__)); \ } else { \ ASSERTC(0, "Callback is NULL", 0); \ } \ } while (0) namespace { // all access to this variable should be done on the jni thread std::set remote_bdaddr_cache; std::queue remote_bdaddr_cache_ordered; const size_t remote_bdaddr_cache_max_size = 1024; void btif_address_cache_add(const RawAddress& p_bda, uint8_t addr_type) { // Remove the oldest entries while (remote_bdaddr_cache.size() >= remote_bdaddr_cache_max_size) { const RawAddress& raw_address = remote_bdaddr_cache_ordered.front(); remote_bdaddr_cache.erase(raw_address); remote_bdaddr_cache_ordered.pop(); } remote_bdaddr_cache.insert(p_bda); remote_bdaddr_cache_ordered.push(p_bda); } bool btif_address_cache_find(const RawAddress& p_bda) { return (remote_bdaddr_cache.find(p_bda) != remote_bdaddr_cache.end()); } void btif_address_cache_init(void) { remote_bdaddr_cache.clear(); remote_bdaddr_cache_ordered = {}; } void bta_batch_scan_threshold_cb(tBTM_BLE_REF_VALUE ref_value) { SCAN_CBACK_IN_JNI(batchscan_threshold_cb, ref_value); } void bta_batch_scan_reports_cb(int client_id, tBTM_STATUS status, uint8_t report_format, uint8_t num_records, std::vector data) { SCAN_CBACK_IN_JNI(batchscan_reports_cb, client_id, status, report_format, num_records, std::move(data)); } void bta_scan_results_cb_impl(RawAddress bd_addr, tBT_DEVICE_TYPE device_type, int8_t rssi, tBLE_ADDR_TYPE addr_type, uint16_t ble_evt_type, uint8_t ble_primary_phy, uint8_t ble_secondary_phy, uint8_t ble_advertising_sid, int8_t ble_tx_power, uint16_t ble_periodic_adv_int, vector value) { uint8_t remote_name_len; bt_device_type_t dev_type; bt_property_t properties; const uint8_t* p_eir_remote_name = AdvertiseDataParser::GetFieldByType( value, BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len); if (p_eir_remote_name == NULL) { p_eir_remote_name = AdvertiseDataParser::GetFieldByType( value, BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len); } if ((addr_type != BLE_ADDR_RANDOM) || (p_eir_remote_name)) { if (!btif_address_cache_find(bd_addr)) { btif_address_cache_add(bd_addr, addr_type); if (p_eir_remote_name) { if (remote_name_len > BD_NAME_LEN + 1 || (remote_name_len == BD_NAME_LEN + 1 && p_eir_remote_name[BD_NAME_LEN] != '\0')) { LOG_INFO("%s dropping invalid packet - device name too long: %d", __func__, remote_name_len); return; } bt_bdname_t bdname; memcpy(bdname.name, p_eir_remote_name, remote_name_len); if (remote_name_len < BD_NAME_LEN + 1) bdname.name[remote_name_len] = '\0'; LOG_VERBOSE("%s BLE device name=%s len=%d dev_type=%d", __func__, bdname.name, remote_name_len, device_type); btif_dm_update_ble_remote_properties(bd_addr, bdname.name, device_type); } } } dev_type = (bt_device_type_t)device_type; BTIF_STORAGE_FILL_PROPERTY(&properties, BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &dev_type); btif_storage_set_remote_device_property(&(bd_addr), &properties); btif_storage_set_remote_addr_type(&bd_addr, addr_type); HAL_CBACK(bt_gatt_callbacks, scanner->scan_result_cb, ble_evt_type, addr_type, &bd_addr, ble_primary_phy, ble_secondary_phy, ble_advertising_sid, ble_tx_power, rssi, ble_periodic_adv_int, std::move(value)); } void bta_scan_results_cb(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_data) { uint8_t len; if (event == BTA_DM_INQ_CMPL_EVT) { BTIF_TRACE_DEBUG("%s BLE observe complete. Num Resp %d", __func__, p_data->inq_cmpl.num_resps); return; } if (event != BTA_DM_INQ_RES_EVT) { BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event); return; } vector value; if (p_data->inq_res.p_eir) { value.insert(value.begin(), p_data->inq_res.p_eir, p_data->inq_res.p_eir + p_data->inq_res.eir_len); if (AdvertiseDataParser::GetFieldByType( value, BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &len)) { p_data->inq_res.remt_name_not_required = true; } } tBTA_DM_INQ_RES* r = &p_data->inq_res; do_in_jni_thread(Bind(bta_scan_results_cb_impl, r->bd_addr, r->device_type, r->rssi, r->ble_addr_type, r->ble_evt_type, r->ble_primary_phy, r->ble_secondary_phy, r->ble_advertising_sid, r->ble_tx_power, r->ble_periodic_adv_int, std::move(value))); } void bta_track_adv_event_cb(tBTM_BLE_TRACK_ADV_DATA* p_track_adv_data) { btgatt_track_adv_info_t* btif_scan_track_cb = new btgatt_track_adv_info_t; BTIF_TRACE_DEBUG("%s", __func__); btif_gatt_move_track_adv_data(btif_scan_track_cb, (btgatt_track_adv_info_t*)p_track_adv_data); SCAN_CBACK_IN_JNI(track_adv_event_cb, Owned(btif_scan_track_cb)); } void bta_cback(tBTA_GATTC_EVT, tBTA_GATTC*) {} class BleScannerInterfaceImpl : public BleScannerInterface { ~BleScannerInterfaceImpl() override{}; void RegisterScanner(const bluetooth::Uuid& app_uuid, RegisterCallback cb) override { do_in_main_thread(FROM_HERE, Bind( [](RegisterCallback cb) { BTA_GATTC_AppRegister( bta_cback, jni_thread_wrapper(FROM_HERE, std::move(cb)), false); }, std::move(cb))); } void Unregister(int scanner_id) override { do_in_main_thread(FROM_HERE, Bind(&BTA_GATTC_AppDeregister, scanner_id)); } void Scan(bool start) override { do_in_jni_thread(Bind( [](bool start) { if (!start) { do_in_main_thread(FROM_HERE, Bind(&BTA_DmBleObserve, false, 0, nullptr)); return; } btif_address_cache_init(); do_in_main_thread( FROM_HERE, Bind(&BTA_DmBleObserve, true, 0, bta_scan_results_cb)); }, start)); } void ScanFilterParamSetup( uint8_t client_if, uint8_t action, uint8_t filt_index, std::unique_ptr filt_param, FilterParamSetupCallback cb) override { BTIF_TRACE_DEBUG("%s", __func__); if (filt_param && filt_param->dely_mode == 1) { do_in_main_thread( FROM_HERE, base::Bind(BTM_BleTrackAdvertiser, bta_track_adv_event_cb, client_if)); } do_in_main_thread( FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, action, filt_index, base::Passed(&filt_param), jni_thread_wrapper(FROM_HERE, std::move(cb)))); } void ScanFilterAdd(int filter_index, std::vector filters, FilterConfigCallback cb) override { BTIF_TRACE_DEBUG("%s: %d", __func__, filter_index); do_in_main_thread( FROM_HERE, base::Bind( &BTM_LE_PF_set, filter_index, std::move(filters), jni_thread_wrapper( FROM_HERE, Bind(std::move(cb), 0 /*TODO: this used to be filter type, unused ?*/)))); } void ScanFilterClear(int filter_index, FilterConfigCallback cb) override { BTIF_TRACE_DEBUG("%s: filter_index: %d", __func__, filter_index); do_in_main_thread( FROM_HERE, base::Bind(&BTM_LE_PF_clear, filter_index, jni_thread_wrapper( FROM_HERE, Bind(cb, BTM_BLE_PF_TYPE_ALL)))); } void ScanFilterEnable(bool enable, EnableCallback cb) override { BTIF_TRACE_DEBUG("%s: enable: %d", __func__, enable); uint8_t action = enable ? 1 : 0; do_in_main_thread(FROM_HERE, base::Bind(&BTM_BleEnableDisableFilterFeature, action, jni_thread_wrapper(FROM_HERE, std::move(cb)))); } void SetScanParameters(int scan_interval, int scan_window, Callback cb) override { do_in_main_thread( FROM_HERE, base::Bind(&BTM_BleSetScanParams, scan_interval, scan_window, BTM_BLE_SCAN_MODE_ACTI, jni_thread_wrapper(FROM_HERE, std::move(cb)))); } void BatchscanConfigStorage(int client_if, int batch_scan_full_max, int batch_scan_trunc_max, int batch_scan_notify_threshold, Callback cb) override { do_in_main_thread( FROM_HERE, base::Bind(&BTM_BleSetStorageConfig, (uint8_t)batch_scan_full_max, (uint8_t)batch_scan_trunc_max, (uint8_t)batch_scan_notify_threshold, jni_thread_wrapper(FROM_HERE, cb), bta_batch_scan_threshold_cb, (tBTM_BLE_REF_VALUE)client_if)); } void BatchscanEnable(int scan_mode, int scan_interval, int scan_window, int addr_type, int discard_rule, Callback cb) override { do_in_main_thread( FROM_HERE, base::Bind(&BTM_BleEnableBatchScan, scan_mode, scan_interval, scan_window, discard_rule, static_cast(addr_type), jni_thread_wrapper(FROM_HERE, cb))); } void BatchscanDisable(Callback cb) override { do_in_main_thread(FROM_HERE, base::Bind(&BTM_BleDisableBatchScan, jni_thread_wrapper(FROM_HERE, cb))); } void BatchscanReadReports(int client_if, int scan_mode) override { do_in_main_thread( FROM_HERE, base::Bind(&BTM_BleReadScanReports, (tBLE_SCAN_MODE)scan_mode, Bind(bta_batch_scan_reports_cb, client_if))); } void StartSync(uint8_t sid, RawAddress address, uint16_t skip, uint16_t timeout, StartSyncCb start_cb, SyncReportCb report_cb, SyncLostCb lost_cb) override {} void StopSync(uint16_t handle) override {} void RegisterCallbacks(ScanningCallbacks* callbacks) { // For GD only } }; BleScannerInterface* btLeScannerInstance = nullptr; } // namespace BleScannerInterface* get_ble_scanner_instance() { if (bluetooth::shim::is_gd_scanning_enabled()) { LOG_INFO("Use gd le scanner"); return bluetooth::shim::get_ble_scanner_instance(); } else if (btLeScannerInstance == nullptr) { btLeScannerInstance = new BleScannerInterfaceImpl(); } return btLeScannerInstance; }