/****************************************************************************** * * Copyright (C) 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 "btcore/include/bdaddr.h" #include "btif_common.h" #include "btif_util.h" #include #include "advertise_data_parser.h" #include "bta_api.h" #include "bta_closure_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 "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 std { template <> struct hash { size_t operator()(const bt_bdaddr_t& f) const { return f.address[0] + f.address[1] + f.address[2] + f.address[3] + f.address[4] + f.address[5]; } }; template <> struct equal_to { size_t operator()(const bt_bdaddr_t& x, const bt_bdaddr_t& y) const { return memcmp(x.address, y.address, BD_ADDR_LEN); } }; } namespace { // all access to this variable should be done on the jni thread std::unordered_set p_dev_cb; void btif_gattc_add_remote_bdaddr(BD_ADDR p_bda, uint8_t addr_type) { bt_bdaddr_t bd_addr; memcpy(bd_addr.address, p_bda, BD_ADDR_LEN); p_dev_cb.insert(bd_addr); } bool btif_gattc_find_bdaddr(BD_ADDR p_bda) { bt_bdaddr_t bd_addr; memcpy(bd_addr.address, p_bda, BD_ADDR_LEN); return (p_dev_cb.count(bd_addr) != 0); } void btif_gattc_init_dev_cb(void) { p_dev_cb.clear(); } void btif_gatts_upstreams_evt(uint16_t event, char* p_param) { LOG_VERBOSE(LOG_TAG, "%s: Event %d", __func__, event); tBTA_GATTC* p_data = (tBTA_GATTC*)p_param; switch (event) { case BTA_GATTC_DEREG_EVT: break; case BTA_GATTC_SEARCH_CMPL_EVT: { HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb, p_data->search_cmpl.conn_id, p_data->search_cmpl.status); break; } default: LOG_DEBUG(LOG_TAG, "%s: Unhandled event (%d)", __func__, event); break; } } void bta_gatts_cback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { bt_status_t status = btif_transfer_context(btif_gatts_upstreams_evt, (uint16_t)event, (char*)p_data, sizeof(tBTA_GATTC), NULL); ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status); } 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, tBTA_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(bt_bdaddr_t bd_addr, tBT_DEVICE_TYPE device_type, int8_t rssi, uint8_t 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_gattc_find_bdaddr(bd_addr.address)) { btif_gattc_add_remote_bdaddr(bd_addr.address, 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(LOG_TAG, "%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(LOG_TAG, "%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.address, 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; bt_bdaddr_t bdaddr; bdcpy(bdaddr.address, r->bd_addr); do_in_jni_thread(Bind(bta_scan_results_cb_impl, bdaddr, 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)); } class BleScannerInterfaceImpl : public BleScannerInterface { ~BleScannerInterfaceImpl(){}; void RegisterScanner(RegisterCallback cb) override { do_in_bta_thread(FROM_HERE, Bind( [](RegisterCallback cb) { BTA_GATTC_AppRegister( bta_gatts_cback, jni_thread_wrapper(FROM_HERE, std::move(cb))); }, std::move(cb))); } void Unregister(int scanner_id) override { do_in_bta_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_bta_thread(FROM_HERE, Bind(&BTA_DmBleObserve, false, 0, nullptr)); return; } btif_gattc_init_dev_cb(); do_in_bta_thread(FROM_HERE, Bind(&BTA_DmBleObserve, true, 0, (tBTA_DM_SEARCH_CBACK*)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_bta_thread( FROM_HERE, base::Bind(BTM_BleTrackAdvertiser, bta_track_adv_event_cb, client_if)); } do_in_bta_thread(FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, action, filt_index, base::Passed(&filt_param), jni_thread_wrapper(FROM_HERE, std::move(cb)))); } void ScanFilterAddRemove(int action, int filt_type, int filt_index, int company_id, int company_id_mask, const bt_uuid_t* p_uuid, const bt_uuid_t* p_uuid_mask, const bt_bdaddr_t* bd_addr, char addr_type, vector data, vector mask, FilterConfigCallback cb) override { BTIF_TRACE_DEBUG("%s, %d, %d", __func__, action, filt_type); /* If data is passed, both mask and data have to be the same length */ if (data.size() != mask.size() && data.size() != 0 && mask.size() != 0) return; switch (filt_type) { case BTM_BLE_PF_ADDR_FILTER: { tBLE_BD_ADDR target_addr; bdcpy(target_addr.bda, bd_addr->address); target_addr.type = addr_type; do_in_bta_thread( FROM_HERE, base::Bind(&BTM_LE_PF_addr_filter, action, filt_index, std::move(target_addr), jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type)))); return; } case BTM_BLE_PF_SRVC_DATA: do_in_bta_thread(FROM_HERE, base::Bind(&BTM_LE_PF_srvc_data, action, filt_index)); return; case BTM_BLE_PF_SRVC_UUID: case BTM_BLE_PF_SRVC_SOL_UUID: { tBT_UUID bt_uuid; btif_to_bta_uuid(&bt_uuid, p_uuid); if (p_uuid_mask == NULL) { do_in_bta_thread( FROM_HERE, base::Bind(&BTM_LE_PF_uuid_filter, action, filt_index, filt_type, bt_uuid, BTM_BLE_PF_LOGIC_AND, nullptr, jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type)))); return; } tBTM_BLE_PF_COND_MASK* mask = new tBTM_BLE_PF_COND_MASK; btif_to_bta_uuid_mask(mask, p_uuid_mask, p_uuid); do_in_bta_thread( FROM_HERE, base::Bind(&BTM_LE_PF_uuid_filter, action, filt_index, filt_type, bt_uuid, BTM_BLE_PF_LOGIC_AND, base::Owned(mask), jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type)))); return; } case BTM_BLE_PF_LOCAL_NAME: { do_in_bta_thread( FROM_HERE, base::Bind(&BTM_LE_PF_local_name, action, filt_index, std::move(data), jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type)))); return; } case BTM_BLE_PF_MANU_DATA: { do_in_bta_thread( FROM_HERE, base::Bind(&BTM_LE_PF_manu_data, action, filt_index, company_id, company_id_mask, std::move(data), std::move(mask), jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type)))); return; } case BTM_BLE_PF_SRVC_DATA_PATTERN: { do_in_bta_thread( FROM_HERE, base::Bind(&BTM_LE_PF_srvc_data_pattern, action, filt_index, std::move(data), std::move(mask), jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type)))); return; } default: LOG_ERROR(LOG_TAG, "%s: Unknown filter type (%d)!", __func__, action); return; } } void ScanFilterClear(int filter_index, FilterConfigCallback cb) override { BTIF_TRACE_DEBUG("%s: filter_index: %d", __func__, filter_index); do_in_bta_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_bta_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_bta_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_bta_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_bta_thread( FROM_HERE, base::Bind(&BTM_BleEnableBatchScan, scan_mode, scan_interval, scan_window, discard_rule, addr_type, jni_thread_wrapper(FROM_HERE, cb))); } void BatchscanDisable(Callback cb) override { do_in_bta_thread(FROM_HERE, base::Bind(&BTM_BleDisableBatchScan, jni_thread_wrapper(FROM_HERE, cb))); } void BatchscanReadReports(int client_if, int scan_mode) override { do_in_bta_thread(FROM_HERE, base::Bind(&BTM_BleReadScanReports, (uint8_t)scan_mode, Bind(bta_batch_scan_reports_cb, client_if))); } void StartSync(uint8_t sid, bt_bdaddr_t address, uint16_t skip, uint16_t timeout, StartSyncCb start_cb, SyncReportCb report_cb, SyncLostCb lost_cb) override {} void StopSync(uint16_t handle) override {} }; BleScannerInterface* btLeScannerInstance = nullptr; } // namespace BleScannerInterface* get_ble_scanner_instance() { if (btLeScannerInstance == nullptr) btLeScannerInstance = new BleScannerInterfaceImpl(); return btLeScannerInstance; }