Separate LE scanner and GATT client BTIF interfaces (3/3)
In order to properly separate low level structures associated with LE
scanner and GATT client, their interfaces must be separated first.
Test: sl4a BleScanApiTest
Bug: 30622771
Change-Id: If804632c8e4b08fd15d5b847c7838822cf98d79f
diff --git a/btif/Android.mk b/btif/Android.mk
index d5deb20..46696bf 100644
--- a/btif/Android.mk
+++ b/btif/Android.mk
@@ -36,6 +36,7 @@
src/btif_av.cc \
src/btif_avrcp_audio_track.cc \
src/btif_ble_advertiser.cc \
+ src/btif_ble_scanner.cc \
src/btif_config.cc \
src/btif_config_transcode.cc \
src/btif_core.cc \
diff --git a/btif/BUILD.gn b/btif/BUILD.gn
index 972fc15..b3d9504 100644
--- a/btif/BUILD.gn
+++ b/btif/BUILD.gn
@@ -26,6 +26,7 @@
#TODO(jpawlowski): heavily depends on Android,
# "src/btif_avrcp_audio_track.cc",
"src/btif_ble_advertiser.cc",
+ "src/btif_ble_scanner.cc",
"src/btif_config.cc",
"src/btif_config_transcode.cc",
"src/btif_core.cc",
diff --git a/btif/include/btif_gatt.h b/btif/include/btif_gatt.h
index 3ddff43..c5d56b0 100644
--- a/btif/include/btif_gatt.h
+++ b/btif/include/btif_gatt.h
@@ -29,6 +29,7 @@
extern const btgatt_client_interface_t btgattClientInterface;
extern const btgatt_server_interface_t btgattServerInterface;
+extern const btgatt_scanner_interface_t btgattScannerInterface;
BleAdvertiserInterface* get_ble_advertiser_instance();
#endif
diff --git a/btif/src/btif_ble_scanner.cc b/btif/src/btif_ble_scanner.cc
new file mode 100644
index 0000000..eac3906
--- /dev/null
+++ b/btif/src/btif_ble_scanner.cc
@@ -0,0 +1,668 @@
+/******************************************************************************
+ *
+ * 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 <base/bind.h>
+#include <base/threading/thread.h>
+#include <errno.h>
+#include <hardware/bluetooth.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unordered_set>
+#include "device/include/controller.h"
+
+#include "btcore/include/bdaddr.h"
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (BLE_INCLUDED == TRUE)
+
+#include <hardware/bt_gatt.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 "vendor_api.h"
+
+using base::Bind;
+using base::Owned;
+using std::vector;
+
+extern bt_status_t do_in_jni_thread(const base::Closure& task);
+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)
+
+#define CHECK_BTGATT_INIT() \
+ do { \
+ if (bt_gatt_callbacks == NULL) { \
+ LOG_WARN(LOG_TAG, "%s: BTGATT not initialized", __func__); \
+ return BT_STATUS_NOT_READY; \
+ } else { \
+ LOG_VERBOSE(LOG_TAG, "%s", __func__); \
+ } \
+ } while (0)
+
+namespace std {
+template <>
+struct hash<bt_bdaddr_t> {
+ 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<bt_bdaddr_t> {
+ size_t operator()(const bt_bdaddr_t& x, const bt_bdaddr_t& y) const {
+ return memcmp(x.address, y.address, BD_ADDR_LEN);
+ }
+};
+}
+
+namespace {
+
+std::unordered_set<bt_bdaddr_t> 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(); }
+
+btgattc_error_t btif_gattc_translate_btm_status(tBTM_STATUS status) {
+ switch (status) {
+ case BTM_SUCCESS:
+ case BTM_SUCCESS_NO_SECURITY:
+ return BT_GATTC_COMMAND_SUCCESS;
+
+ case BTM_CMD_STARTED:
+ return BT_GATTC_COMMAND_STARTED;
+
+ case BTM_BUSY:
+ return BT_GATTC_COMMAND_BUSY;
+
+ case BTM_CMD_STORED:
+ return BT_GATTC_COMMAND_STORED;
+
+ case BTM_NO_RESOURCES:
+ return BT_GATTC_NO_RESOURCES;
+
+ case BTM_MODE_UNSUPPORTED:
+ case BTM_WRONG_MODE:
+ case BTM_MODE4_LEVEL4_NOT_SUPPORTED:
+ return BT_GATTC_MODE_UNSUPPORTED;
+
+ case BTM_ILLEGAL_VALUE:
+ case BTM_SCO_BAD_LENGTH:
+ return BT_GATTC_ILLEGAL_VALUE;
+
+ case BTM_UNKNOWN_ADDR:
+ return BT_GATTC_UNKNOWN_ADDR;
+
+ case BTM_DEVICE_TIMEOUT:
+ return BT_GATTC_DEVICE_TIMEOUT;
+
+ case BTM_FAILED_ON_SECURITY:
+ case BTM_REPEATED_ATTEMPTS:
+ case BTM_NOT_AUTHORIZED:
+ return BT_GATTC_SECURITY_ERROR;
+
+ case BTM_DEV_RESET:
+ case BTM_ILLEGAL_ACTION:
+ return BT_GATTC_INCORRECT_STATE;
+
+ case BTM_BAD_VALUE_RET:
+ return BT_GATTC_INVALID_CONTROLLER_OUTPUT;
+
+ case BTM_DELAY_CHECK:
+ return BT_GATTC_DELAYED_ENCRYPTION_CHECK;
+
+ case BTM_ERR_PROCESSING:
+ default:
+ return BT_GATTC_ERR_PROCESSING;
+ }
+}
+
+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_REG_EVT: {
+ bt_uuid_t app_uuid;
+ bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.app_uuid);
+ HAL_CBACK(bt_gatt_callbacks, scanner->register_scanner_cb,
+ p_data->reg_oper.status, p_data->reg_oper.client_if, &app_uuid);
+ break;
+ }
+
+ 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_ERROR(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_scan_param_setup_cb(tGATT_IF client_if, tBTM_STATUS status) {
+ SCAN_CBACK_IN_JNI(scan_parameter_setup_completed_cb, client_if,
+ btif_gattc_translate_btm_status(status));
+}
+
+void bta_scan_filt_cfg_cb(tBTA_DM_BLE_PF_ACTION action,
+ tBTA_DM_BLE_SCAN_COND_OP cfg_op,
+ tBTA_DM_BLE_PF_AVBL_SPACE avbl_space,
+ tBTA_STATUS status, tBTA_DM_BLE_REF_VALUE ref_value) {
+ SCAN_CBACK_IN_JNI(scan_filter_cfg_cb, action, ref_value, status, cfg_op,
+ avbl_space);
+}
+
+void bta_scan_filt_param_setup_cb(uint8_t action_type,
+ tBTA_DM_BLE_PF_AVBL_SPACE avbl_space,
+ tBTA_DM_BLE_REF_VALUE ref_value,
+ tBTA_STATUS status) {
+ SCAN_CBACK_IN_JNI(scan_filter_param_cb, action_type, ref_value, status,
+ avbl_space);
+}
+
+void bta_scan_filt_status_cb(uint8_t action, tBTA_STATUS status,
+ tBTA_DM_BLE_REF_VALUE ref_value) {
+ SCAN_CBACK_IN_JNI(scan_filter_status_cb, action, ref_value, status);
+}
+
+void bta_batch_scan_setup_cb(tBTA_BLE_BATCH_SCAN_EVT evt,
+ tBTA_DM_BLE_REF_VALUE ref_value,
+ tBTA_STATUS status) {
+ BTIF_TRACE_DEBUG("bta_batch_scan_setup_cb-Status:%x, client_if:%d, evt=%d",
+ status, ref_value, evt);
+
+ switch (evt) {
+ case BTA_BLE_BATCH_SCAN_ENB_EVT: {
+ SCAN_CBACK_IN_JNI(batchscan_enb_disable_cb, 1, ref_value, status);
+ return;
+ }
+
+ case BTA_BLE_BATCH_SCAN_DIS_EVT: {
+ SCAN_CBACK_IN_JNI(batchscan_enb_disable_cb, 0, ref_value, status);
+ return;
+ }
+
+ case BTA_BLE_BATCH_SCAN_CFG_STRG_EVT: {
+ SCAN_CBACK_IN_JNI(batchscan_cfg_storage_cb, ref_value, status);
+ return;
+ }
+
+ case BTA_BLE_BATCH_SCAN_DATA_EVT: {
+ SCAN_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, 0, 0,
+ vector<uint8_t>());
+ return;
+ }
+
+ case BTA_BLE_BATCH_SCAN_THRES_EVT: {
+ SCAN_CBACK_IN_JNI(batchscan_threshold_cb, ref_value);
+ return;
+ }
+
+ default:
+ return;
+ }
+}
+
+void bta_batch_scan_threshold_cb(tBTA_DM_BLE_REF_VALUE ref_value) {
+ SCAN_CBACK_IN_JNI(batchscan_threshold_cb, ref_value);
+}
+
+void bta_batch_scan_reports_cb(tBTA_DM_BLE_REF_VALUE ref_value,
+ uint8_t report_format, uint8_t num_records,
+ uint16_t data_len, uint8_t* p_rep_data,
+ tBTA_STATUS status) {
+ BTIF_TRACE_DEBUG("%s - client_if:%d, %d, %d, %d", __func__, ref_value, status,
+ num_records, data_len);
+
+ if (data_len > 0) {
+ vector<uint8_t> data(p_rep_data, p_rep_data + data_len);
+ osi_free(p_rep_data);
+
+ SCAN_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, report_format,
+ num_records, std::move(data));
+ } else {
+ SCAN_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, report_format,
+ num_records, vector<uint8_t>());
+ }
+}
+
+void bta_scan_results_cb_impl(bt_bdaddr_t bd_addr, tBT_DEVICE_TYPE device_type,
+ int8_t rssi, uint8_t addr_type,
+ vector<uint8_t> value) {
+ uint8_t remote_name_len;
+ const uint8_t* p_eir_remote_name = NULL;
+ bt_device_type_t dev_type;
+ bt_property_t properties;
+
+ p_eir_remote_name = BTM_CheckEirData(
+ value.data(), BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
+
+ if (p_eir_remote_name == NULL) {
+ p_eir_remote_name = BTM_CheckEirData(
+ value.data(), 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) {
+ bt_bdname_t bdname;
+ memcpy(bdname.name, p_eir_remote_name, remote_name_len);
+ 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, &bd_addr, rssi,
+ 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<uint8_t> value(BTGATT_MAX_ATTR_LEN);
+ if (p_data->inq_res.p_eir) {
+ value.insert(value.begin(), p_data->inq_res.p_eir,
+ p_data->inq_res.p_eir + 62);
+
+ if (BTM_CheckEirData(p_data->inq_res.p_eir,
+ BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &len)) {
+ p_data->inq_res.remt_name_not_required = true;
+ }
+ }
+
+ bt_bdaddr_t bdaddr;
+ bdcpy(bdaddr.address, p_data->inq_res.bd_addr);
+ do_in_jni_thread(Bind(bta_scan_results_cb_impl, bdaddr,
+ p_data->inq_res.device_type, p_data->inq_res.rssi,
+ p_data->inq_res.ble_addr_type, std::move(value)));
+}
+
+void bta_track_adv_event_cb(tBTA_DM_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 btif_gattc_register_scanner_impl(tBT_UUID uuid) {
+ BTA_GATTC_AppRegister(&uuid, bta_gatts_cback);
+}
+
+bt_status_t btif_gattc_register_scanner(bt_uuid_t* uuid) {
+ CHECK_BTGATT_INIT();
+
+ tBT_UUID bt_uuid;
+ btif_to_bta_uuid(&bt_uuid, uuid);
+ return do_in_jni_thread(Bind(&btif_gattc_register_scanner_impl, bt_uuid));
+}
+
+void btif_gattc_unregister_scanner_impl(int client_if) {
+ BTA_GATTC_AppDeregister(client_if);
+}
+
+bt_status_t btif_gattc_unregister_scanner(int scanner_id) {
+ CHECK_BTGATT_INIT();
+ return do_in_jni_thread(Bind(&btif_gattc_unregister_scanner_impl, scanner_id));
+}
+
+bt_status_t btif_gattc_scan(bool start) {
+ CHECK_BTGATT_INIT();
+ if (start) {
+ btif_gattc_init_dev_cb();
+ return do_in_jni_thread(Bind(&BTA_DmBleObserve, true, 0,
+ (tBTA_DM_SEARCH_CBACK*)bta_scan_results_cb));
+ }
+
+ return do_in_jni_thread(Bind(&BTA_DmBleObserve, false, 0, nullptr));
+}
+
+void btif_gattc_scan_filter_param_setup_impl(
+ int client_if, uint8_t action, int filt_index,
+ tBTA_DM_BLE_PF_FILT_PARAMS* adv_filt_param) {
+ if (1 == adv_filt_param->dely_mode) {
+ BTA_DmBleTrackAdvertiser(client_if, bta_track_adv_event_cb);
+ }
+
+ BTA_DmBleScanFilterSetup(action, filt_index, adv_filt_param, NULL,
+ bta_scan_filt_param_setup_cb, client_if);
+}
+
+bt_status_t btif_gattc_scan_filter_param_setup(
+ btgatt_filt_param_setup_t filt_param) {
+ CHECK_BTGATT_INIT();
+ BTIF_TRACE_DEBUG("%s", __func__);
+
+ tBTA_DM_BLE_PF_FILT_PARAMS* adv_filt_param = new tBTA_DM_BLE_PF_FILT_PARAMS;
+ adv_filt_param->feat_seln = filt_param.feat_seln;
+ adv_filt_param->list_logic_type = filt_param.list_logic_type;
+ adv_filt_param->filt_logic_type = filt_param.filt_logic_type;
+ adv_filt_param->rssi_high_thres = filt_param.rssi_high_thres;
+ adv_filt_param->rssi_low_thres = filt_param.rssi_low_thres;
+ adv_filt_param->dely_mode = filt_param.dely_mode;
+ adv_filt_param->found_timeout = filt_param.found_timeout;
+ adv_filt_param->lost_timeout = filt_param.lost_timeout;
+ adv_filt_param->found_timeout_cnt = filt_param.found_timeout_cnt;
+ adv_filt_param->num_of_tracking_entries = filt_param.num_of_tracking_entries;
+
+ return do_in_jni_thread(
+ Bind(base::IgnoreResult(&btif_gattc_scan_filter_param_setup_impl),
+ filt_param.client_if, filt_param.action, filt_param.filt_index,
+ base::Owned(adv_filt_param)));
+}
+
+void btif_gattc_scan_filter_add_srvc_uuid(tBT_UUID uuid,
+ tBTA_DM_BLE_PF_COND_MASK* p_uuid_mask,
+ int action, int filt_type,
+ int filt_index, int client_if) {
+ tBTA_DM_BLE_PF_COND_PARAM cond;
+ memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
+
+ cond.srvc_uuid.p_target_addr = NULL;
+ cond.srvc_uuid.cond_logic = BTA_DM_BLE_PF_LOGIC_AND;
+ cond.srvc_uuid.uuid = uuid;
+ cond.srvc_uuid.p_uuid_mask = p_uuid_mask;
+
+ BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond,
+ &bta_scan_filt_cfg_cb, client_if);
+}
+
+void btif_gattc_scan_filter_add_local_name(vector<uint8_t> data, int action,
+ int filt_type, int filt_index,
+ int client_if) {
+ tBTA_DM_BLE_PF_COND_PARAM cond;
+ memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
+
+ cond.local_name.data_len = data.size();
+ cond.local_name.p_data = const_cast<uint8_t*>(data.data());
+ BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond,
+ &bta_scan_filt_cfg_cb, client_if);
+}
+
+void btif_gattc_scan_filter_add_manu_data(int company_id, int company_id_mask,
+ vector<uint8_t> pattern,
+ vector<uint8_t> pattern_mask,
+ int action, int filt_type,
+ int filt_index, int client_if) {
+ tBTA_DM_BLE_PF_COND_PARAM cond;
+ memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
+
+ cond.manu_data.company_id = company_id;
+ cond.manu_data.company_id_mask = company_id_mask ? company_id_mask : 0xFFFF;
+ cond.manu_data.data_len = pattern.size();
+ cond.manu_data.p_pattern = const_cast<uint8_t*>(pattern.data());
+ cond.manu_data.p_pattern_mask = const_cast<uint8_t*>(pattern_mask.data());
+ BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond,
+ &bta_scan_filt_cfg_cb, client_if);
+}
+
+void btif_gattc_scan_filter_add_data_pattern(vector<uint8_t> pattern,
+ vector<uint8_t> pattern_mask,
+ int action, int filt_type,
+ int filt_index, int client_if) {
+ tBTA_DM_BLE_PF_COND_PARAM cond;
+ memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
+
+ cond.srvc_data.data_len = pattern.size();
+ cond.srvc_data.p_pattern = const_cast<uint8_t*>(pattern.data());
+ cond.srvc_data.p_pattern_mask = const_cast<uint8_t*>(pattern_mask.data());
+ BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond,
+ &bta_scan_filt_cfg_cb, client_if);
+}
+
+bt_status_t btif_gattc_scan_filter_add_remove(
+ int client_if, 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<uint8_t> data,
+ vector<uint8_t> mask) {
+ CHECK_BTGATT_INIT();
+ 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 BT_STATUS_PARM_INVALID;
+
+ switch (filt_type) {
+ case BTA_DM_BLE_PF_ADDR_FILTER:
+ {
+ tBTA_DM_BLE_PF_COND_PARAM* cond = new tBTA_DM_BLE_PF_COND_PARAM;
+ memset(cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
+
+ bdcpy(cond->target_addr.bda, bd_addr->address);
+ cond->target_addr.type = addr_type;
+ return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action,
+ filt_type, filt_index, base::Owned(cond),
+ &bta_scan_filt_cfg_cb, client_if));
+ }
+
+ case BTA_DM_BLE_PF_SRVC_DATA:
+ return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action,
+ filt_type, filt_index, nullptr,
+ &bta_scan_filt_cfg_cb, client_if));
+
+ case BTA_DM_BLE_PF_SRVC_UUID:
+ {
+ tBT_UUID bt_uuid;
+ btif_to_bta_uuid(&bt_uuid, p_uuid);
+
+ if (p_uuid_mask != NULL) {
+ tBTA_DM_BLE_PF_COND_MASK* uuid_mask = new tBTA_DM_BLE_PF_COND_MASK;
+ btif_to_bta_uuid_mask(uuid_mask, p_uuid_mask, p_uuid);
+ return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_srvc_uuid,
+ bt_uuid, base::Owned(uuid_mask), action,
+ filt_type, filt_index, client_if));
+ }
+
+ return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_srvc_uuid,
+ bt_uuid, nullptr, action, filt_type,
+ filt_index, client_if));
+ }
+
+ case BTA_DM_BLE_PF_SRVC_SOL_UUID:
+ {
+ tBTA_DM_BLE_PF_COND_PARAM* cond = new tBTA_DM_BLE_PF_COND_PARAM;
+ memset(cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
+
+ cond->solicitate_uuid.p_target_addr = NULL;
+ cond->solicitate_uuid.cond_logic = BTA_DM_BLE_PF_LOGIC_AND;
+ btif_to_bta_uuid(&cond->solicitate_uuid.uuid, p_uuid);
+
+ return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action,
+ filt_type, filt_index, base::Owned(cond),
+ &bta_scan_filt_cfg_cb, client_if));
+ }
+
+ case BTA_DM_BLE_PF_LOCAL_NAME:
+ {
+ return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_local_name,
+ std::move(data), action, filt_type,
+ filt_index, client_if));
+ }
+
+ case BTA_DM_BLE_PF_MANU_DATA:
+ {
+ return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_manu_data,
+ company_id, company_id_mask, std::move(data),
+ std::move(mask), action, filt_type,
+ filt_index, client_if));
+ }
+
+ case BTA_DM_BLE_PF_SRVC_DATA_PATTERN:
+ {
+ return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_data_pattern,
+ std::move(data), std::move(mask), action,
+ filt_type, filt_index, client_if));
+ }
+
+ default:
+ LOG_ERROR(LOG_TAG, "%s: Unknown filter type (%d)!", __func__, action);
+ return (bt_status_t)BTA_GATT_OK;
+ }
+}
+
+bt_status_t btif_gattc_scan_filter_clear(int client_if, int filter_index) {
+ CHECK_BTGATT_INIT();
+ BTIF_TRACE_DEBUG("%s: filter_index: %d", __func__, filter_index);
+
+ return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition,
+ BTA_DM_BLE_SCAN_COND_CLEAR,
+ BTA_DM_BLE_PF_TYPE_ALL, filter_index, nullptr,
+ &bta_scan_filt_cfg_cb, client_if));
+}
+
+bt_status_t btif_gattc_scan_filter_enable(int client_if, bool enable) {
+ CHECK_BTGATT_INIT();
+ BTIF_TRACE_DEBUG("%s: enable: %d", __func__, enable);
+
+ uint8_t action = enable ? 1 : 0;
+
+ return do_in_jni_thread(Bind(&BTA_DmEnableScanFilter, action,
+ &bta_scan_filt_status_cb, client_if));
+}
+
+bt_status_t btif_gattc_set_scan_parameters(int client_if, int scan_interval,
+ int scan_window) {
+ CHECK_BTGATT_INIT();
+ return do_in_jni_thread(
+ Bind(BTA_DmSetBleScanParams, client_if, scan_interval, scan_window,
+ BTM_BLE_SCAN_MODE_ACTI,
+ (tBLE_SCAN_PARAM_SETUP_CBACK)bta_scan_param_setup_cb));
+}
+
+
+bt_status_t btif_gattc_cfg_storage(int client_if, int batch_scan_full_max,
+ int batch_scan_trunc_max,
+ int batch_scan_notify_threshold) {
+ CHECK_BTGATT_INIT();
+ return do_in_jni_thread(
+ Bind(BTA_DmBleSetStorageParams, batch_scan_full_max, batch_scan_trunc_max,
+ batch_scan_notify_threshold,
+ (tBTA_BLE_SCAN_SETUP_CBACK*)bta_batch_scan_setup_cb,
+ (tBTA_BLE_SCAN_THRESHOLD_CBACK*)bta_batch_scan_threshold_cb,
+ (tBTA_BLE_SCAN_REP_CBACK*)bta_batch_scan_reports_cb,
+ (tBTA_DM_BLE_REF_VALUE)client_if));
+}
+
+bt_status_t btif_gattc_enb_batch_scan(int client_if, int scan_mode,
+ int scan_interval, int scan_window,
+ int addr_type, int discard_rule) {
+ CHECK_BTGATT_INIT();
+ return do_in_jni_thread(Bind(BTA_DmBleEnableBatchScan, scan_mode,
+ scan_interval, scan_window, discard_rule,
+ addr_type, client_if));
+}
+
+bt_status_t btif_gattc_dis_batch_scan(int client_if) {
+ CHECK_BTGATT_INIT();
+ return do_in_jni_thread(Bind(BTA_DmBleDisableBatchScan, client_if));
+}
+
+bt_status_t btif_gattc_read_batch_scan_reports(int client_if, int scan_mode) {
+ CHECK_BTGATT_INIT();
+ return do_in_jni_thread(Bind(BTA_DmBleReadScanReports, scan_mode, client_if));
+}
+
+} //namespace
+
+const btgatt_scanner_interface_t btgattScannerInterface = {
+ btif_gattc_register_scanner,
+ btif_gattc_unregister_scanner,
+ btif_gattc_scan,
+ btif_gattc_scan_filter_param_setup,
+ btif_gattc_scan_filter_add_remove,
+ btif_gattc_scan_filter_clear,
+ btif_gattc_scan_filter_enable,
+ btif_gattc_set_scan_parameters,
+ btif_gattc_cfg_storage,
+ btif_gattc_enb_batch_scan,
+ btif_gattc_dis_batch_scan,
+ btif_gattc_read_batch_scan_reports,
+};
+
+#endif
diff --git a/btif/src/btif_gatt.cc b/btif/src/btif_gatt.cc
index d9926e2..8465d37 100644
--- a/btif/src/btif_gatt.cc
+++ b/btif/src/btif_gatt.cc
@@ -84,6 +84,7 @@
&btgattClientInterface,
&btgattServerInterface,
+ &btgattScannerInterface,
nullptr // filled in btif_gatt_get_interface
};
diff --git a/btif/src/btif_gatt_client.cc b/btif/src/btif_gatt_client.cc
index a83fc09..53a3b5c 100644
--- a/btif/src/btif_gatt_client.cc
+++ b/btif/src/btif_gatt_client.cc
@@ -31,10 +31,8 @@
#include <base/threading/thread.h>
#include <errno.h>
#include <hardware/bluetooth.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unordered_set>
#include "device/include/controller.h"
#include "btcore/include/bdaddr.h"
@@ -95,96 +93,10 @@
#define BTM_BLE_IS_RESOLVE_BDA(x) \
(((x)[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
-namespace std {
-template <>
-struct hash<bt_bdaddr_t> {
- 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<bt_bdaddr_t> {
- size_t operator()(const bt_bdaddr_t& x, const bt_bdaddr_t& y) const {
- return memcmp(x.address, y.address, BD_ADDR_LEN);
- }
-};
-}
-
namespace {
-std::unordered_set<bt_bdaddr_t> p_dev_cb;
uint8_t rssi_request_client_if;
-btgattc_error_t btif_gattc_translate_btm_status(tBTM_STATUS status) {
- switch (status) {
- case BTM_SUCCESS:
- case BTM_SUCCESS_NO_SECURITY:
- return BT_GATTC_COMMAND_SUCCESS;
-
- case BTM_CMD_STARTED:
- return BT_GATTC_COMMAND_STARTED;
-
- case BTM_BUSY:
- return BT_GATTC_COMMAND_BUSY;
-
- case BTM_CMD_STORED:
- return BT_GATTC_COMMAND_STORED;
-
- case BTM_NO_RESOURCES:
- return BT_GATTC_NO_RESOURCES;
-
- case BTM_MODE_UNSUPPORTED:
- case BTM_WRONG_MODE:
- case BTM_MODE4_LEVEL4_NOT_SUPPORTED:
- return BT_GATTC_MODE_UNSUPPORTED;
-
- case BTM_ILLEGAL_VALUE:
- case BTM_SCO_BAD_LENGTH:
- return BT_GATTC_ILLEGAL_VALUE;
-
- case BTM_UNKNOWN_ADDR:
- return BT_GATTC_UNKNOWN_ADDR;
-
- case BTM_DEVICE_TIMEOUT:
- return BT_GATTC_DEVICE_TIMEOUT;
-
- case BTM_FAILED_ON_SECURITY:
- case BTM_REPEATED_ATTEMPTS:
- case BTM_NOT_AUTHORIZED:
- return BT_GATTC_SECURITY_ERROR;
-
- case BTM_DEV_RESET:
- case BTM_ILLEGAL_ACTION:
- return BT_GATTC_INCORRECT_STATE;
-
- case BTM_BAD_VALUE_RET:
- return BT_GATTC_INVALID_CONTROLLER_OUTPUT;
-
- case BTM_DELAY_CHECK:
- return BT_GATTC_DELAYED_ENCRYPTION_CHECK;
-
- case BTM_ERR_PROCESSING:
- default:
- return BT_GATTC_ERR_PROCESSING;
- }
-}
-
-void btif_gattc_init_dev_cb(void) { p_dev_cb.clear(); }
-
-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_upstreams_evt(uint16_t event, char* p_param) {
LOG_VERBOSE(LOG_TAG, "%s: Event %d", __func__, event);
@@ -297,186 +209,6 @@
ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
}
-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_REG_EVT: {
- bt_uuid_t app_uuid;
- bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.app_uuid);
- HAL_CBACK(bt_gatt_callbacks, client->register_scanner_cb,
- p_data->reg_oper.status, p_data->reg_oper.client_if, &app_uuid);
- break;
- }
-
- 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_ERROR(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_setup_cb(tBTA_BLE_BATCH_SCAN_EVT evt,
- tBTA_DM_BLE_REF_VALUE ref_value,
- tBTA_STATUS status) {
- BTIF_TRACE_DEBUG("bta_batch_scan_setup_cb-Status:%x, client_if:%d, evt=%d",
- status, ref_value, evt);
-
- switch (evt) {
- case BTA_BLE_BATCH_SCAN_ENB_EVT: {
- CLI_CBACK_IN_JNI(batchscan_enb_disable_cb, 1, ref_value, status);
- return;
- }
-
- case BTA_BLE_BATCH_SCAN_DIS_EVT: {
- CLI_CBACK_IN_JNI(batchscan_enb_disable_cb, 0, ref_value, status);
- return;
- }
-
- case BTA_BLE_BATCH_SCAN_CFG_STRG_EVT: {
- CLI_CBACK_IN_JNI(batchscan_cfg_storage_cb, ref_value, status);
- return;
- }
-
- case BTA_BLE_BATCH_SCAN_DATA_EVT: {
- CLI_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, 0, 0,
- vector<uint8_t>());
- return;
- }
-
- case BTA_BLE_BATCH_SCAN_THRES_EVT: {
- CLI_CBACK_IN_JNI(batchscan_threshold_cb, ref_value);
- return;
- }
-
- default:
- return;
- }
-}
-
-void bta_batch_scan_threshold_cb(tBTA_DM_BLE_REF_VALUE ref_value) {
- CLI_CBACK_IN_JNI(batchscan_threshold_cb, ref_value);
-}
-
-void bta_batch_scan_reports_cb(tBTA_DM_BLE_REF_VALUE ref_value,
- uint8_t report_format, uint8_t num_records,
- uint16_t data_len, uint8_t* p_rep_data,
- tBTA_STATUS status) {
- BTIF_TRACE_DEBUG("%s - client_if:%d, %d, %d, %d", __func__, ref_value, status,
- num_records, data_len);
-
- if (data_len > 0) {
- vector<uint8_t> data(p_rep_data, p_rep_data + data_len);
- osi_free(p_rep_data);
-
- CLI_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, report_format,
- num_records, std::move(data));
- } else {
- CLI_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, report_format,
- num_records, vector<uint8_t>());
- }
-}
-
-void bta_scan_results_cb_impl(bt_bdaddr_t bd_addr, tBT_DEVICE_TYPE device_type,
- int8_t rssi, uint8_t addr_type,
- vector<uint8_t> value) {
- uint8_t remote_name_len;
- const uint8_t* p_eir_remote_name = NULL;
- bt_device_type_t dev_type;
- bt_property_t properties;
-
- p_eir_remote_name = BTM_CheckEirData(
- value.data(), BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
-
- if (p_eir_remote_name == NULL) {
- p_eir_remote_name = BTM_CheckEirData(
- value.data(), 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) {
- bt_bdname_t bdname;
- memcpy(bdname.name, p_eir_remote_name, remote_name_len);
- 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, client->scan_result_cb, &bd_addr, rssi,
- 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<uint8_t> value(BTGATT_MAX_ATTR_LEN);
- if (p_data->inq_res.p_eir) {
- value.insert(value.begin(), p_data->inq_res.p_eir,
- p_data->inq_res.p_eir + 62);
-
- if (BTM_CheckEirData(p_data->inq_res.p_eir,
- BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &len)) {
- p_data->inq_res.remt_name_not_required = true;
- }
- }
-
- bt_bdaddr_t bdaddr;
- bdcpy(bdaddr.address, p_data->inq_res.bd_addr);
- do_in_jni_thread(Bind(bta_scan_results_cb_impl, bdaddr,
- p_data->inq_res.device_type, p_data->inq_res.rssi,
- p_data->inq_res.ble_addr_type, std::move(value)));
-}
-
-void bta_track_adv_event_cb(tBTA_DM_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);
-
- CLI_CBACK_IN_JNI(track_adv_event_cb, Owned(btif_scan_track_cb));
-}
void btm_read_rssi_cb(tBTM_RSSI_RESULTS* p_result) {
if (!p_result) return;
@@ -487,32 +219,6 @@
base::Owned(addr), p_result->rssi, p_result->status);
}
-void bta_scan_param_setup_cb(tGATT_IF client_if, tBTM_STATUS status) {
- CLI_CBACK_IN_JNI(scan_parameter_setup_completed_cb, client_if,
- btif_gattc_translate_btm_status(status));
-}
-
-void bta_scan_filt_cfg_cb(tBTA_DM_BLE_PF_ACTION action,
- tBTA_DM_BLE_SCAN_COND_OP cfg_op,
- tBTA_DM_BLE_PF_AVBL_SPACE avbl_space,
- tBTA_STATUS status, tBTA_DM_BLE_REF_VALUE ref_value) {
- CLI_CBACK_IN_JNI(scan_filter_cfg_cb, action, ref_value, status, cfg_op,
- avbl_space);
-}
-
-void bta_scan_filt_param_setup_cb(uint8_t action_type,
- tBTA_DM_BLE_PF_AVBL_SPACE avbl_space,
- tBTA_DM_BLE_REF_VALUE ref_value,
- tBTA_STATUS status) {
- CLI_CBACK_IN_JNI(scan_filter_param_cb, action_type, ref_value, status,
- avbl_space);
-}
-
-void bta_scan_filt_status_cb(uint8_t action, tBTA_STATUS status,
- tBTA_DM_BLE_REF_VALUE ref_value) {
- CLI_CBACK_IN_JNI(scan_filter_status_cb, action, ref_value, status);
-}
-
/*******************************************************************************
* Client API Functions
*******************************************************************************/
@@ -538,40 +244,6 @@
return do_in_jni_thread(Bind(&btif_gattc_unregister_app_impl, client_if));
}
-
-void btif_gattc_register_scanner_impl(tBT_UUID uuid) {
- BTA_GATTC_AppRegister(&uuid, bta_gatts_cback);
-}
-
-bt_status_t btif_gattc_register_scanner(bt_uuid_t* uuid) {
- CHECK_BTGATT_INIT();
-
- tBT_UUID bt_uuid;
- btif_to_bta_uuid(&bt_uuid, uuid);
- return do_in_jni_thread(Bind(&btif_gattc_register_scanner_impl, bt_uuid));
-}
-
-void btif_gattc_unregister_scanner_impl(int client_if) {
- BTA_GATTC_AppDeregister(client_if);
-}
-
-bt_status_t btif_gattc_unregister_scanner(int scanner_id) {
- CHECK_BTGATT_INIT();
- return do_in_jni_thread(Bind(&btif_gattc_unregister_scanner_impl, scanner_id));
-}
-
-
-bt_status_t btif_gattc_scan(bool start) {
- CHECK_BTGATT_INIT();
- if (start) {
- btif_gattc_init_dev_cb();
- return do_in_jni_thread(Bind(&BTA_DmBleObserve, true, 0,
- (tBTA_DM_SEARCH_CBACK*)bta_scan_results_cb));
- } else {
- return do_in_jni_thread(Bind(&BTA_DmBleObserve, false, 0, nullptr));
- }
-}
-
void btif_gattc_open_impl(int client_if, BD_ADDR address, bool is_direct,
int transport_p) {
// Ensure device is in inquiry database
@@ -869,216 +541,6 @@
min_interval, max_interval, latency, timeout));
}
-void btif_gattc_scan_filter_param_setup_impl(
- int client_if, uint8_t action, int filt_index,
- tBTA_DM_BLE_PF_FILT_PARAMS* adv_filt_param) {
- if (1 == adv_filt_param->dely_mode)
- BTA_DmBleTrackAdvertiser(client_if, bta_track_adv_event_cb);
- BTA_DmBleScanFilterSetup(action, filt_index, adv_filt_param, NULL,
- bta_scan_filt_param_setup_cb, client_if);
-}
-
-bt_status_t btif_gattc_scan_filter_param_setup(
- btgatt_filt_param_setup_t filt_param) {
- CHECK_BTGATT_INIT();
- BTIF_TRACE_DEBUG("%s", __func__);
-
- tBTA_DM_BLE_PF_FILT_PARAMS* adv_filt_param = new tBTA_DM_BLE_PF_FILT_PARAMS;
- adv_filt_param->feat_seln = filt_param.feat_seln;
- adv_filt_param->list_logic_type = filt_param.list_logic_type;
- adv_filt_param->filt_logic_type = filt_param.filt_logic_type;
- adv_filt_param->rssi_high_thres = filt_param.rssi_high_thres;
- adv_filt_param->rssi_low_thres = filt_param.rssi_low_thres;
- adv_filt_param->dely_mode = filt_param.dely_mode;
- adv_filt_param->found_timeout = filt_param.found_timeout;
- adv_filt_param->lost_timeout = filt_param.lost_timeout;
- adv_filt_param->found_timeout_cnt = filt_param.found_timeout_cnt;
- adv_filt_param->num_of_tracking_entries = filt_param.num_of_tracking_entries;
-
- return do_in_jni_thread(
- Bind(base::IgnoreResult(&btif_gattc_scan_filter_param_setup_impl),
- filt_param.client_if, filt_param.action, filt_param.filt_index,
- base::Owned(adv_filt_param)));
-}
-
-void btif_gattc_scan_filter_add_srvc_uuid(tBT_UUID uuid,
- tBTA_DM_BLE_PF_COND_MASK* p_uuid_mask,
- int action, int filt_type,
- int filt_index, int client_if) {
- tBTA_DM_BLE_PF_COND_PARAM cond;
- memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
-
- cond.srvc_uuid.p_target_addr = NULL;
- cond.srvc_uuid.cond_logic = BTA_DM_BLE_PF_LOGIC_AND;
- cond.srvc_uuid.uuid = uuid;
- cond.srvc_uuid.p_uuid_mask = p_uuid_mask;
-
- BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond,
- &bta_scan_filt_cfg_cb, client_if);
-}
-
-void btif_gattc_scan_filter_add_local_name(vector<uint8_t> data, int action,
- int filt_type, int filt_index,
- int client_if) {
- tBTA_DM_BLE_PF_COND_PARAM cond;
- memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
-
- cond.local_name.data_len = data.size();
- cond.local_name.p_data = const_cast<uint8_t*>(data.data());
- BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond,
- &bta_scan_filt_cfg_cb, client_if);
-}
-
-void btif_gattc_scan_filter_add_manu_data(int company_id, int company_id_mask,
- vector<uint8_t> pattern,
- vector<uint8_t> pattern_mask,
- int action, int filt_type,
- int filt_index, int client_if) {
- tBTA_DM_BLE_PF_COND_PARAM cond;
- memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
-
- cond.manu_data.company_id = company_id;
- cond.manu_data.company_id_mask = company_id_mask ? company_id_mask : 0xFFFF;
- cond.manu_data.data_len = pattern.size();
- cond.manu_data.p_pattern = const_cast<uint8_t*>(pattern.data());
- cond.manu_data.p_pattern_mask = const_cast<uint8_t*>(pattern_mask.data());
- BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond,
- &bta_scan_filt_cfg_cb, client_if);
-}
-
-void btif_gattc_scan_filter_add_data_pattern(vector<uint8_t> pattern,
- vector<uint8_t> pattern_mask,
- int action, int filt_type,
- int filt_index, int client_if) {
- tBTA_DM_BLE_PF_COND_PARAM cond;
- memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
-
- cond.srvc_data.data_len = pattern.size();
- cond.srvc_data.p_pattern = const_cast<uint8_t*>(pattern.data());
- cond.srvc_data.p_pattern_mask = const_cast<uint8_t*>(pattern_mask.data());
- BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond,
- &bta_scan_filt_cfg_cb, client_if);
-}
-
-bt_status_t btif_gattc_scan_filter_add_remove(
- int client_if, 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<uint8_t> data,
- vector<uint8_t> mask) {
- CHECK_BTGATT_INIT();
- 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 BT_STATUS_PARM_INVALID;
-
- switch (filt_type) {
- case BTA_DM_BLE_PF_ADDR_FILTER: // 0
- {
- tBTA_DM_BLE_PF_COND_PARAM* cond = new tBTA_DM_BLE_PF_COND_PARAM;
- memset(cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
-
- bdcpy(cond->target_addr.bda, bd_addr->address);
- cond->target_addr.type = addr_type;
- return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action,
- filt_type, filt_index, base::Owned(cond),
- &bta_scan_filt_cfg_cb, client_if));
- }
-
- case BTA_DM_BLE_PF_SRVC_DATA: // 1
- return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action,
- filt_type, filt_index, nullptr,
- &bta_scan_filt_cfg_cb, client_if));
-
- case BTA_DM_BLE_PF_SRVC_UUID: // 2
- {
- tBT_UUID bt_uuid;
- btif_to_bta_uuid(&bt_uuid, p_uuid);
-
- if (p_uuid_mask != NULL) {
- tBTA_DM_BLE_PF_COND_MASK* uuid_mask = new tBTA_DM_BLE_PF_COND_MASK;
- btif_to_bta_uuid_mask(uuid_mask, p_uuid_mask, p_uuid);
- return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_srvc_uuid,
- bt_uuid, base::Owned(uuid_mask), action,
- filt_type, filt_index, client_if));
- }
-
- return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_srvc_uuid,
- bt_uuid, nullptr, action, filt_type,
- filt_index, client_if));
- }
-
- case BTA_DM_BLE_PF_SRVC_SOL_UUID: // 3
- {
- tBTA_DM_BLE_PF_COND_PARAM* cond = new tBTA_DM_BLE_PF_COND_PARAM;
- memset(cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
-
- cond->solicitate_uuid.p_target_addr = NULL;
- cond->solicitate_uuid.cond_logic = BTA_DM_BLE_PF_LOGIC_AND;
- btif_to_bta_uuid(&cond->solicitate_uuid.uuid, p_uuid);
-
- return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action,
- filt_type, filt_index, base::Owned(cond),
- &bta_scan_filt_cfg_cb, client_if));
- }
-
- case BTA_DM_BLE_PF_LOCAL_NAME: // 4
- {
- return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_local_name,
- std::move(data), action, filt_type,
- filt_index, client_if));
- }
-
- case BTA_DM_BLE_PF_MANU_DATA: // 5
- {
- return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_manu_data,
- company_id, company_id_mask, std::move(data),
- std::move(mask), action, filt_type,
- filt_index, client_if));
- }
-
- case BTA_DM_BLE_PF_SRVC_DATA_PATTERN: // 6
- {
- return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_data_pattern,
- std::move(data), std::move(mask), action,
- filt_type, filt_index, client_if));
- }
-
- default:
- LOG_ERROR(LOG_TAG, "%s: Unknown filter type (%d)!", __func__, action);
- return (bt_status_t)BTA_GATT_OK;
- }
-}
-
-bt_status_t btif_gattc_scan_filter_clear(int client_if, int filter_index) {
- CHECK_BTGATT_INIT();
- BTIF_TRACE_DEBUG("%s: filter_index: %d", __func__, filter_index);
-
- return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition,
- BTA_DM_BLE_SCAN_COND_CLEAR,
- BTA_DM_BLE_PF_TYPE_ALL, filter_index, nullptr,
- &bta_scan_filt_cfg_cb, client_if));
-}
-
-bt_status_t btif_gattc_scan_filter_enable(int client_if, bool enable) {
- CHECK_BTGATT_INIT();
- BTIF_TRACE_DEBUG("%s: enable: %d", __func__, enable);
-
- uint8_t action = enable ? 1 : 0;
-
- return do_in_jni_thread(Bind(&BTA_DmEnableScanFilter, action,
- &bta_scan_filt_status_cb, client_if));
-}
-
-bt_status_t btif_gattc_set_scan_parameters(int client_if, int scan_interval,
- int scan_window) {
- CHECK_BTGATT_INIT();
- return do_in_jni_thread(
- Bind(BTA_DmSetBleScanParams, client_if, scan_interval, scan_window,
- BTM_BLE_SCAN_MODE_ACTI,
- (tBLE_SCAN_PARAM_SETUP_CBACK)bta_scan_param_setup_cb));
-}
-
int btif_gattc_get_device_type(const bt_bdaddr_t* bd_addr) {
int device_type = 0;
char bd_addr_str[18] = {0};
@@ -1089,38 +551,6 @@
return 0;
}
-bt_status_t btif_gattc_cfg_storage(int client_if, int batch_scan_full_max,
- int batch_scan_trunc_max,
- int batch_scan_notify_threshold) {
- CHECK_BTGATT_INIT();
- return do_in_jni_thread(
- Bind(BTA_DmBleSetStorageParams, batch_scan_full_max, batch_scan_trunc_max,
- batch_scan_notify_threshold,
- (tBTA_BLE_SCAN_SETUP_CBACK*)bta_batch_scan_setup_cb,
- (tBTA_BLE_SCAN_THRESHOLD_CBACK*)bta_batch_scan_threshold_cb,
- (tBTA_BLE_SCAN_REP_CBACK*)bta_batch_scan_reports_cb,
- (tBTA_DM_BLE_REF_VALUE)client_if));
-}
-
-bt_status_t btif_gattc_enb_batch_scan(int client_if, int scan_mode,
- int scan_interval, int scan_window,
- int addr_type, int discard_rule) {
- CHECK_BTGATT_INIT();
- return do_in_jni_thread(Bind(BTA_DmBleEnableBatchScan, scan_mode,
- scan_interval, scan_window, discard_rule,
- addr_type, client_if));
-}
-
-bt_status_t btif_gattc_dis_batch_scan(int client_if) {
- CHECK_BTGATT_INIT();
- return do_in_jni_thread(Bind(BTA_DmBleDisableBatchScan, client_if));
-}
-
-bt_status_t btif_gattc_read_batch_scan_reports(int client_if, int scan_mode) {
- CHECK_BTGATT_INIT();
- return do_in_jni_thread(Bind(BTA_DmBleReadScanReports, scan_mode, client_if));
-}
-
bt_status_t btif_gattc_test_command(int command, btgatt_test_params_t* params) {
return btif_gattc_test_command_impl(command, params);
}
@@ -1130,9 +560,6 @@
const btgatt_client_interface_t btgattClientInterface = {
btif_gattc_register_app,
btif_gattc_unregister_app,
- btif_gattc_register_scanner,
- btif_gattc_unregister_scanner,
- btif_gattc_scan,
btif_gattc_open,
btif_gattc_close,
btif_gattc_listen,
@@ -1146,18 +573,9 @@
btif_gattc_reg_for_notification,
btif_gattc_dereg_for_notification,
btif_gattc_read_remote_rssi,
- btif_gattc_scan_filter_param_setup,
- btif_gattc_scan_filter_add_remove,
- btif_gattc_scan_filter_clear,
- btif_gattc_scan_filter_enable,
btif_gattc_get_device_type,
btif_gattc_configure_mtu,
btif_gattc_conn_parameter_update,
- btif_gattc_set_scan_parameters,
- btif_gattc_cfg_storage,
- btif_gattc_enb_batch_scan,
- btif_gattc_dis_batch_scan,
- btif_gattc_read_batch_scan_reports,
btif_gattc_test_command,
btif_gattc_get_gatt_db};
diff --git a/service/Android.mk b/service/Android.mk
index 5bcd54e..51e5671 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -61,6 +61,8 @@
common/android/bluetooth/IBluetoothGattServerCallback.aidl \
common/android/bluetooth/IBluetoothLeAdvertiser.aidl \
common/android/bluetooth/IBluetoothLeAdvertiserCallback.aidl \
+ common/android/bluetooth/IBluetoothLeScanner.aidl \
+ common/android/bluetooth/IBluetoothLeScannerCallback.aidl \
common/android/bluetooth/IBluetoothLowEnergy.aidl \
common/android/bluetooth/IBluetoothLowEnergyCallback.aidl \
common/android/bluetooth/advertise_data.cc \
@@ -90,6 +92,7 @@
ipc/ipc_manager.cc \
logging_helpers.cc \
low_energy_advertiser.cc \
+ low_energy_scanner.cc \
low_energy_client.cc \
settings.cc
@@ -102,6 +105,7 @@
ipc/binder/bluetooth_gatt_client_binder_server.cc \
ipc/binder/bluetooth_gatt_server_binder_server.cc \
ipc/binder/bluetooth_le_advertiser_binder_server.cc \
+ ipc/binder/bluetooth_le_scanner_binder_server.cc \
ipc/binder/bluetooth_low_energy_binder_server.cc \
ipc/binder/interface_with_instances_base.cc \
ipc/binder/ipc_handler_binder.cc \
@@ -126,6 +130,7 @@
test/gatt_server_unittest.cc \
test/low_energy_advertiser_unittest.cc \
test/low_energy_client_unittest.cc \
+ test/low_energy_scanner_unittest.cc \
test/settings_unittest.cc \
test/util_unittest.cc \
test/uuid_unittest.cc
diff --git a/service/BUILD.gn b/service/BUILD.gn
index 50b01ff..19134c1 100644
--- a/service/BUILD.gn
+++ b/service/BUILD.gn
@@ -42,6 +42,7 @@
"ipc/linux_ipc_host.cc",
"logging_helpers.cc",
"low_energy_advertiser.cc",
+ "low_energy_scanner.cc",
"low_energy_client.cc",
"settings.cc",
]
diff --git a/service/adapter.cc b/service/adapter.cc
index ede0ab2..e97b595 100644
--- a/service/adapter.cc
+++ b/service/adapter.cc
@@ -30,6 +30,7 @@
#include "service/hal/bluetooth_interface.h"
#include "service/logging_helpers.h"
#include "service/low_energy_advertiser.h"
+#include "service/low_energy_scanner.h"
#include "service/low_energy_client.h"
using std::lock_guard;
@@ -80,6 +81,7 @@
hal::BluetoothInterface::Get()->AddObserver(this);
ble_client_factory_.reset(new LowEnergyClientFactory(*this));
ble_advertiser_factory_.reset(new LowEnergyAdvertiserFactory());
+ ble_scanner_factory_.reset(new LowEnergyScannerFactory(*this));
gatt_client_factory_.reset(new GattClientFactory());
gatt_server_factory_.reset(new GattServerFactory());
hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties();
@@ -223,6 +225,10 @@
return ble_advertiser_factory_.get();
}
+ LowEnergyScannerFactory* GetLeScannerFactory() const override {
+ return ble_scanner_factory_.get();
+ }
+
GattClientFactory* GetGattClientFactory() const override {
return gatt_client_factory_.get();
}
@@ -395,6 +401,9 @@
// Factory used to create per-app LeAdvertiser instances.
std::unique_ptr<LowEnergyAdvertiserFactory> ble_advertiser_factory_;
+ // Factory used to create per-app LeScanner instances.
+ std::unique_ptr<LowEnergyScannerFactory> ble_scanner_factory_;
+
// Factory used to create per-app GattClient instances.
std::unique_ptr<GattClientFactory> gatt_client_factory_;
diff --git a/service/adapter.h b/service/adapter.h
index 9c2be86..75a5491 100644
--- a/service/adapter.h
+++ b/service/adapter.h
@@ -27,6 +27,7 @@
class GattClientFactory;
class GattServerFactory;
class LowEnergyAdvertiserFactory;
+class LowEnergyScannerFactory;
class LowEnergyClientFactory;
// Represents the local Bluetooth adapter.
@@ -126,6 +127,10 @@
// operations.
virtual LowEnergyClientFactory* GetLowEnergyClientFactory() const = 0;
+ // Returns a pointer to the LowEnergyScannerFactory. This can be used to
+ // register per-application LowEnergyScanner instances to perform scanning.
+ virtual LowEnergyScannerFactory* GetLeScannerFactory() const = 0;
+
// Returns a pointer to the LowEnergyAdvertiserFactory. This can be used to
// register per-application LowEnergyAdvertiser instances to perform advertising.
virtual LowEnergyAdvertiserFactory* GetLeAdvertiserFactory() const = 0;
diff --git a/service/client/main.cc b/service/client/main.cc
index 8c1dd5e..442b751 100644
--- a/service/client/main.cc
+++ b/service/client/main.cc
@@ -37,9 +37,11 @@
#include <android/bluetooth/BnBluetoothGattClientCallback.h>
#include <android/bluetooth/BnBluetoothLowEnergyCallback.h>
#include <android/bluetooth/BnBluetoothLeAdvertiserCallback.h>
+#include <android/bluetooth/BnBluetoothLeScannerCallback.h>
#include <android/bluetooth/IBluetooth.h>
#include <android/bluetooth/IBluetoothGattClient.h>
#include <android/bluetooth/IBluetoothLeAdvertiser.h>
+#include <android/bluetooth/IBluetoothLeScanner.h>
#include <android/bluetooth/IBluetoothLowEnergy.h>
#include <bluetooth/low_energy_constants.h>
#include <bluetooth/scan_filter.h>
@@ -58,6 +60,7 @@
using android::bluetooth::IBluetooth;
using android::bluetooth::IBluetoothGattClient;
using android::bluetooth::IBluetoothLeAdvertiser;
+using android::bluetooth::IBluetoothLeScanner;
using android::bluetooth::IBluetoothLowEnergy;
namespace {
@@ -100,6 +103,11 @@
std::atomic_bool ble_advertiser_registering(false);
std::atomic_int ble_advertiser_id(0);
+// The registered IBluetoothLeScanner handle. If |ble_scanner_registering| is
+// true then an operation to register the scanner is in progress.
+std::atomic_bool ble_scanner_registering(false);
+std::atomic_int ble_scanner_id(0);
+
// The registered IBluetoothGattClient client handle. If |gatt_registering| is
// true then an operation to register the client is in progress.
std::atomic_bool gatt_registering(false);
@@ -202,22 +210,6 @@
return Status::ok();
}
- Status OnScanResult(
- const android::bluetooth::ScanResult& scan_result) override {
- BeginAsyncOut();
- cout << COLOR_BOLDWHITE "Scan result: " << COLOR_BOLDYELLOW "["
- << scan_result.device_address() << "] "
- << COLOR_BOLDWHITE "- RSSI: " << scan_result.rssi() << COLOR_OFF;
-
- if (dump_scan_record) {
- cout << " - Record: "
- << base::HexEncode(scan_result.scan_record().data(),
- scan_result.scan_record().size());
- }
- EndAsyncOut();
- return Status::ok();
- }
-
private:
DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback);
};
@@ -259,6 +251,48 @@
DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeAdvertiserCallback);
};
+class CLIBluetoothLeScannerCallback
+ : public android::bluetooth::BnBluetoothLeScannerCallback {
+ public:
+ CLIBluetoothLeScannerCallback() = default;
+ ~CLIBluetoothLeScannerCallback() override = default;
+
+ // IBluetoothLowEnergyCallback overrides:
+ Status OnScannerRegistered(int status, int scanner_id) override {
+ BeginAsyncOut();
+ if (status != bluetooth::BLE_STATUS_SUCCESS) {
+ PrintError("Failed to register BLE client");
+ } else {
+ ble_scanner_id = scanner_id;
+ cout << COLOR_BOLDWHITE "Registered BLE client with ID: " COLOR_OFF
+ << COLOR_GREEN << scanner_id << COLOR_OFF;
+ }
+ EndAsyncOut();
+
+ ble_scanner_registering = false;
+ return Status::ok();
+ }
+
+ Status OnScanResult(
+ const android::bluetooth::ScanResult& scan_result) override {
+ BeginAsyncOut();
+ cout << COLOR_BOLDWHITE "Scan result: " << COLOR_BOLDYELLOW "["
+ << scan_result.device_address() << "] "
+ << COLOR_BOLDWHITE "- RSSI: " << scan_result.rssi() << COLOR_OFF;
+
+ if (dump_scan_record) {
+ cout << " - Record: "
+ << base::HexEncode(scan_result.scan_record().data(),
+ scan_result.scan_record().size());
+ }
+ EndAsyncOut();
+ return Status::ok();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeScannerCallback);
+};
+
class CLIGattClientCallback
: public android::bluetooth::BnBluetoothGattClientCallback {
public:
@@ -787,6 +821,53 @@
PrintCommandStatus(status);
}
+
+void HandleRegisterBLEScanner(IBluetooth* bt_iface, const vector<string>& args) {
+ CHECK_NO_ARGS(args);
+
+ if (ble_scanner_registering.load()) {
+ PrintError("In progress");
+ return;
+ }
+
+ if (ble_scanner_id.load()) {
+ PrintError("Already registered");
+ return;
+ }
+
+ sp<IBluetoothLeScanner> ble_scanner_iface;
+ bt_iface->GetLeScannerInterface(&ble_scanner_iface);
+ if (!ble_scanner_iface.get()) {
+ PrintError("Failed to obtain handle to Bluetooth LE Scanner interface");
+ return;
+ }
+
+ bool status;
+ ble_scanner_iface->RegisterScanner(new CLIBluetoothLeScannerCallback(), &status);
+ ble_scanner_registering = status;
+ PrintCommandStatus(status);
+}
+
+void HandleUnregisterBLEScanner(IBluetooth* bt_iface, const vector<string>& args) {
+ CHECK_NO_ARGS(args);
+
+ if (!ble_scanner_id.load()) {
+ PrintError("Not registered");
+ return;
+ }
+
+ sp<IBluetoothLeScanner> ble_scanner_iface;
+ bt_iface->GetLeScannerInterface(&ble_scanner_iface);
+ if (!ble_scanner_iface.get()) {
+ PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
+ return;
+ }
+
+ ble_scanner_iface->UnregisterScanner(ble_scanner_id.load());
+ ble_scanner_id = 0;
+ PrintCommandStatus(true);
+}
+
void HandleStartLeScan(IBluetooth* bt_iface, const vector<string>& args) {
if (!ble_client_id.load()) {
PrintError("BLE not registered");
@@ -808,10 +889,10 @@
}
}
- sp<IBluetoothLowEnergy> ble_iface;
- bt_iface->GetLowEnergyInterface(&ble_iface);
- if (!ble_iface.get()) {
- PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
+ sp<IBluetoothLeScanner> ble_scanner_iface;
+ bt_iface->GetLeScannerInterface(&ble_scanner_iface);
+ if (!ble_scanner_iface.get()) {
+ PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
return;
}
@@ -819,7 +900,7 @@
std::vector<android::bluetooth::ScanFilter> filters;
bool status;
- ble_iface->StartScan(ble_client_id.load(), settings, filters, &status);
+ ble_scanner_iface->StartScan(ble_scanner_id.load(), settings, filters, &status);
PrintCommandStatus(status);
}
@@ -829,15 +910,15 @@
return;
}
- sp<IBluetoothLowEnergy> ble_iface;
- bt_iface->GetLowEnergyInterface(&ble_iface);
- if (!ble_iface.get()) {
- PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
+ sp<IBluetoothLeScanner> ble_scanner_iface;
+ bt_iface->GetLeScannerInterface(&ble_scanner_iface);
+ if (!ble_scanner_iface.get()) {
+ PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
return;
}
bool status;
- ble_iface->StopScan(ble_client_id.load(), &status);
+ ble_scanner_iface->StopScan(ble_scanner_id.load(), &status);
PrintCommandStatus(status);
}
@@ -880,6 +961,10 @@
{"set-mtu", HandleSetMtu, "\t\tSet MTU (-h for options)"},
{"start-adv", HandleStartAdv, "\t\tStart advertising (-h for options)"},
{"stop-adv", HandleStopAdv, "\t\tStop advertising"},
+ {"register-le-scanner", HandleRegisterBLEScanner,
+ "\t\tRegister with the Bluetooth Low Energy scanner interface"},
+ {"unregister-le-scanner", HandleUnregisterBLEScanner,
+ "\t\tUnregister from the Bluetooth LE scanner interface"},
{"start-le-scan", HandleStartLeScan,
"\t\tStart LE device scan (-h for options)"},
{"stop-le-scan", HandleStopLeScan, "\t\tStop LE device scan"},
diff --git a/service/common/android/bluetooth/IBluetooth.aidl b/service/common/android/bluetooth/IBluetooth.aidl
index 58d3e04..1e96952 100644
--- a/service/common/android/bluetooth/IBluetooth.aidl
+++ b/service/common/android/bluetooth/IBluetooth.aidl
@@ -19,6 +19,7 @@
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothLowEnergy;
import android.bluetooth.IBluetoothLeAdvertiser;
+import android.bluetooth.IBluetoothLeScanner;
import android.bluetooth.IBluetoothGattClient;
import android.bluetooth.IBluetoothGattServer;
@@ -43,6 +44,7 @@
IBluetoothLowEnergy GetLowEnergyInterface();
IBluetoothLeAdvertiser GetLeAdvertiserInterface();
+ IBluetoothLeScanner GetLeScannerInterface();
IBluetoothGattClient GetGattClientInterface();
IBluetoothGattServer GetGattServerInterface();
}
diff --git a/service/common/android/bluetooth/IBluetoothLeScanner.aidl b/service/common/android/bluetooth/IBluetoothLeScanner.aidl
new file mode 100644
index 0000000..2f9506d
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothLeScanner.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetoothLeScannerCallback;
+import android.bluetooth.ScanFilter;
+import android.bluetooth.ScanSettings;
+
+interface IBluetoothLeScanner {
+ boolean RegisterScanner(in IBluetoothLeScannerCallback callback);
+ void UnregisterScanner(int scanner_id);
+ void UnregisterAll();
+
+ boolean StartScan(int client_id,
+ in ScanSettings settings,
+ in ScanFilter[] filters);
+ boolean StopScan(int client_id);
+}
diff --git a/service/common/android/bluetooth/IBluetoothLeScannerCallback.aidl b/service/common/android/bluetooth/IBluetoothLeScannerCallback.aidl
new file mode 100644
index 0000000..4ee6be3
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothLeScannerCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.ScanResult;
+
+oneway interface IBluetoothLeScannerCallback {
+ void OnScannerRegistered(int status, int client_id);
+ void OnScanResult(in ScanResult scan_result);
+}
\ No newline at end of file
diff --git a/service/common/android/bluetooth/IBluetoothLowEnergy.aidl b/service/common/android/bluetooth/IBluetoothLowEnergy.aidl
index cdc8c88..4d49430 100644
--- a/service/common/android/bluetooth/IBluetoothLowEnergy.aidl
+++ b/service/common/android/bluetooth/IBluetoothLowEnergy.aidl
@@ -20,8 +20,6 @@
import android.bluetooth.AdvertiseData;
import android.bluetooth.AdvertiseSettings;
-import android.bluetooth.ScanFilter;
-import android.bluetooth.ScanSettings;
interface IBluetoothLowEnergy {
boolean RegisterClient(in IBluetoothLowEnergyCallback callback);
@@ -32,9 +30,4 @@
boolean Disconnect(int client_id, String address);
boolean SetMtu(int client_id, String address, int mtu);
-
- boolean StartScan(int client_id,
- in ScanSettings settings,
- in ScanFilter[] filters);
- boolean StopScan(int client_id);
}
\ No newline at end of file
diff --git a/service/common/android/bluetooth/IBluetoothLowEnergyCallback.aidl b/service/common/android/bluetooth/IBluetoothLowEnergyCallback.aidl
index 45c5dc8..858506a 100644
--- a/service/common/android/bluetooth/IBluetoothLowEnergyCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothLowEnergyCallback.aidl
@@ -23,5 +23,4 @@
void OnClientRegistered(int status, int client_id);
void OnConnectionState(int status, int client_id, String address, boolean connected);
void OnMtuChanged(int status, String address, int mtu);
- void OnScanResult(in ScanResult scan_result);
}
\ No newline at end of file
diff --git a/service/gatt_server_old.cc b/service/gatt_server_old.cc
index 9622a00..22a4a62 100644
--- a/service/gatt_server_old.cc
+++ b/service/gatt_server_old.cc
@@ -424,8 +424,6 @@
// to refer to the client interface.
const btgatt_client_callbacks_t gatt_client_callbacks = {
RegisterClientCallback,
- RegisterScannerCallback,
- ScanResultCallback,
ClientConnectCallback,
ClientDisconnectCallback,
nullptr, /* search_complete_cb; */
@@ -439,19 +437,25 @@
nullptr, /* read_remote_rssi_cb; */
ListenCallback,
nullptr, /* configure_mtu_cb; */
- nullptr, /* scan_filter_cfg_cb; */
- nullptr, /* scan_filter_param_cb; */
- nullptr, /* scan_filter_status_cb; */
nullptr, /* congestion_cb; */
+ nullptr, /* get_gatt_db_cb; */
+ nullptr, /* services_removed_cb */
+ nullptr, /* services_added_cb */
+};
+
+const btgatt_scanner_callbacks_t gatt_scanner_callbacks = {
+ RegisterScannerCallback,
+ ScanResultCallback,
nullptr, /* batchscan_cfg_storage_cb; */
nullptr, /* batchscan_enb_disable_cb; */
nullptr, /* batchscan_reports_cb; */
nullptr, /* batchscan_threshold_cb; */
nullptr, /* track_adv_event_cb; */
nullptr, /* scan_parameter_setup_completed_cb; */
- nullptr, /* get_gatt_db_cb; */
- nullptr, /* services_removed_cb */
- nullptr, /* services_added_cb */
+ nullptr, /* scan_filter_cfg_cb; */
+ nullptr, /* scan_filter_param_cb; */
+ nullptr, /* scan_filter_status_cb; */
+
};
const btgatt_callbacks_t gatt_callbacks = {
@@ -463,6 +467,9 @@
/** GATT Server callbacks */
&gatt_server_callbacks,
+
+ /** GATT Server callbacks */
+ &gatt_scanner_callbacks,
};
} // namespace
@@ -687,7 +694,7 @@
}
bool Server::ScanEnable() {
- bt_status_t btstat = internal_->gatt->client->scan(true);
+ bt_status_t btstat = internal_->gatt->scanner->scan(true);
if (btstat) {
LOG_ERROR(LOG_TAG, "Enable scan failed: %d", btstat);
return false;
@@ -696,7 +703,7 @@
}
bool Server::ScanDisable() {
- bt_status_t btstat = internal_->gatt->client->scan(false);
+ bt_status_t btstat = internal_->gatt->scanner->scan(false);
if (btstat) {
LOG_ERROR(LOG_TAG, "Disable scan failed: %d", btstat);
return false;
diff --git a/service/hal/bluetooth_gatt_interface.cc b/service/hal/bluetooth_gatt_interface.cc
index dfc85b5..9dc2151 100644
--- a/service/hal/bluetooth_gatt_interface.cc
+++ b/service/hal/bluetooth_gatt_interface.cc
@@ -49,11 +49,17 @@
// Helper for obtaining the observer lists. This is forward declared here
// and defined below since it depends on BluetoothInterfaceImpl.
+base::ObserverList<BluetoothGattInterface::ScannerObserver>*
+ GetScannerObservers();
base::ObserverList<BluetoothGattInterface::ClientObserver>*
GetClientObservers();
base::ObserverList<BluetoothGattInterface::ServerObserver>*
GetServerObservers();
+#define FOR_EACH_SCANNER_OBSERVER(func) \
+ FOR_EACH_OBSERVER(BluetoothGattInterface::ScannerObserver, \
+ *GetScannerObservers(), func)
+
#define FOR_EACH_CLIENT_OBSERVER(func) \
FOR_EACH_OBSERVER(BluetoothGattInterface::ClientObserver, \
*GetClientObservers(), func)
@@ -86,7 +92,7 @@
VERIFY_INTERFACE_OR_RETURN();
CHECK(app_uuid);
- FOR_EACH_CLIENT_OBSERVER(
+ FOR_EACH_SCANNER_OBSERVER(
RegisterScannerCallback(g_interface, status, scanner_id, *app_uuid));
}
@@ -97,7 +103,7 @@
VLOG(2) << __func__ << " - BD_ADDR: " << BtAddrString(bda)
<< " RSSI: " << rssi;
- FOR_EACH_CLIENT_OBSERVER(
+ FOR_EACH_SCANNER_OBSERVER(
ScanResultCallback(g_interface, *bda, rssi, adv_data));
}
@@ -395,10 +401,23 @@
// The HAL Bluetooth GATT client interface callbacks. These signal a mixture of
// GATT client-role and GAP events.
-const btgatt_client_callbacks_t gatt_client_callbacks = {
- RegisterClientCallback,
+
+const btgatt_scanner_callbacks_t gatt_scanner_callbacks = {
RegisterScannerCallback,
ScanResultCallback,
+ nullptr, // batchscan_cfg_storage_cb
+ nullptr, // batchscan_enb_disable_cb
+ nullptr, // batchscan_reports_cb
+ nullptr, // batchscan_threshold_cb
+ nullptr, // track_adv_event_cb
+ nullptr, // scan_parameter_setup_completed_cb
+ nullptr, // scan_filter_cfg_cb
+ nullptr, // scan_filter_param_cb
+ nullptr, // scan_filter_status_cb
+};
+
+const btgatt_client_callbacks_t gatt_client_callbacks = {
+ RegisterClientCallback,
ConnectCallback,
DisconnectCallback,
SearchCompleteCallback,
@@ -412,16 +431,7 @@
nullptr, // read_remote_rssi_cb
ListenCallback,
MtuChangedCallback,
- nullptr, // scan_filter_cfg_cb
- nullptr, // scan_filter_param_cb
- nullptr, // scan_filter_status_cb
nullptr, // congestion_cb
- nullptr, // batchscan_cfg_storage_cb
- nullptr, // batchscan_enb_disable_cb
- nullptr, // batchscan_reports_cb
- nullptr, // batchscan_threshold_cb
- nullptr, // track_adv_event_cb
- nullptr, // scan_parameter_setup_completed_cb
GetGattDbCallback,
ServicesRemovedCallback,
ServicesAddedCallback,
@@ -448,6 +458,7 @@
sizeof(btgatt_callbacks_t),
&gatt_client_callbacks,
&gatt_server_callbacks,
+ &gatt_scanner_callbacks,
};
} // namespace
@@ -463,6 +474,14 @@
hal_iface_->cleanup();
}
+ void AddScannerObserver(ScannerObserver* observer) override {
+ scanner_observers_.AddObserver(observer);
+ }
+
+ void RemoveScannerObserver(ScannerObserver* observer) override {
+ scanner_observers_.RemoveObserver(observer);
+ }
+
void AddClientObserver(ClientObserver* observer) override {
client_observers_.AddObserver(observer);
}
@@ -483,6 +502,10 @@
return hal_iface_->advertiser;
}
+ const btgatt_scanner_interface_t* GetScannerHALInterface() const override {
+ return hal_iface_->scanner;
+ }
+
const btgatt_client_interface_t* GetClientHALInterface() const override {
return hal_iface_->client;
}
@@ -516,6 +539,10 @@
return true;
}
+ base::ObserverList<ScannerObserver>* scanner_observers() {
+ return &scanner_observers_;
+ }
+
base::ObserverList<ClientObserver>* client_observers() {
return &client_observers_;
}
@@ -529,6 +556,7 @@
// We're not using a base::ObserverListThreadSafe, which it posts observer
// events automatically on the origin threads, as we want to avoid that
// overhead and simply forward the events to the upper layer.
+ base::ObserverList<ScannerObserver> scanner_observers_;
base::ObserverList<ClientObserver> client_observers_;
base::ObserverList<ServerObserver> server_observers_;
@@ -541,6 +569,13 @@
namespace {
+base::ObserverList<BluetoothGattInterface::ScannerObserver>*
+GetScannerObservers() {
+ CHECK(g_interface);
+ return static_cast<BluetoothGattInterfaceImpl*>(
+ g_interface)->scanner_observers();
+}
+
base::ObserverList<BluetoothGattInterface::ClientObserver>*
GetClientObservers() {
CHECK(g_interface);
@@ -559,15 +594,8 @@
// Default observer implementations. These are provided so that the methods
// themselves are optional.
-void BluetoothGattInterface::ClientObserver::RegisterClientCallback(
- BluetoothGattInterface* /* gatt_iface */,
- int /* status */,
- int /* client_if */,
- const bt_uuid_t& /* app_uuid */) {
- // Do nothing.
-}
-void BluetoothGattInterface::ClientObserver::RegisterScannerCallback(
+void BluetoothGattInterface::ScannerObserver::RegisterScannerCallback(
BluetoothGattInterface* /* gatt_iface */,
int /* status */,
int /* scanner_id */,
@@ -575,7 +603,7 @@
// Do nothing.
}
-void BluetoothGattInterface::ClientObserver::ScanResultCallback(
+void BluetoothGattInterface::ScannerObserver::ScanResultCallback(
BluetoothGattInterface* /* gatt_iface */,
const bt_bdaddr_t& /* bda */,
int /* rssi */,
@@ -583,6 +611,14 @@
// Do Nothing.
}
+void BluetoothGattInterface::ClientObserver::RegisterClientCallback(
+ BluetoothGattInterface* /* gatt_iface */,
+ int /* status */,
+ int /* client_if */,
+ const bt_uuid_t& /* app_uuid */) {
+ // Do nothing.
+}
+
void BluetoothGattInterface::ClientObserver::ConnectCallback(
BluetoothGattInterface* /* gatt_iface */,
int /* conn_id */,
@@ -861,7 +897,7 @@
// If this is the first scan client, then make a call into the stack. We
// only do this when the reference count changes to or from 0.
if (scan_client_set_.empty()) {
- bt_status_t status = GetClientHALInterface()->scan(true);
+ bt_status_t status = GetScannerHALInterface()->scan(true);
if (status != BT_STATUS_SUCCESS) {
LOG(ERROR) << "HAL call to scan failed";
return status;
@@ -885,7 +921,7 @@
}
if (scan_client_set_.size() == 1) {
- bt_status_t status = GetClientHALInterface()->scan(false);
+ bt_status_t status = GetScannerHALInterface()->scan(false);
if (status != BT_STATUS_SUCCESS) {
LOG(ERROR) << "HAL call to stop scan failed";
return status;
diff --git a/service/hal/bluetooth_gatt_interface.h b/service/hal/bluetooth_gatt_interface.h
index 5a0e989..6cb4e34 100644
--- a/service/hal/bluetooth_gatt_interface.h
+++ b/service/hal/bluetooth_gatt_interface.h
@@ -40,22 +40,19 @@
class BluetoothGattInterface {
public:
- // The standard BT-GATT client callback interface. The HAL interface doesn't
- // allow registering "user data" that carries context beyond the callback
- // parameters, forcing implementations to deal with global variables. The
- // Observer interface is to redirect these events to interested parties in an
- // object-oriented manner.
- class ClientObserver {
+ // The HAL interface doesn't allow registering "user data" that carries
+ // context beyond the callback parameters, forcing implementations to deal
+ // with global variables. The *Observer interface is to redirect these events
+ // to interested parties in an object-oriented manner.
+
+ // The standard LE scanner callback interface.
+ class ScannerObserver {
public:
- virtual ~ClientObserver() = default;
+
+ virtual ~ScannerObserver() = default;
// All of the events below correspond to callbacks defined in
- // "bt_gatt_client_callbacks_t" in the HAL API definitions.
-
- virtual void RegisterClientCallback(
- BluetoothGattInterface* gatt_iface,
- int status, int client_if,
- const bt_uuid_t& app_uuid);
+ // "btgatt_scanner_callbacks_t" in the HAL API definitions.
virtual void RegisterScannerCallback(
BluetoothGattInterface* gatt_iface,
@@ -66,6 +63,21 @@
BluetoothGattInterface* gatt_iface,
const bt_bdaddr_t& bda, int rssi,
vector<uint8_t> adv_data); // NOLINT(pass-by-value)
+ };
+
+ // The standard BT-GATT client callback interface.
+ class ClientObserver {
+ public:
+
+ virtual ~ClientObserver() = default;
+
+ // All of the events below correspond to callbacks defined in
+ // "bt_gatt_client_callbacks_t" in the HAL API definitions.
+
+ virtual void RegisterClientCallback(
+ BluetoothGattInterface* gatt_iface,
+ int status, int client_if,
+ const bt_uuid_t& app_uuid);
virtual void ConnectCallback(
BluetoothGattInterface* gatt_iface,
@@ -229,6 +241,11 @@
// call this re-entrantly from an observer event as this may cause a deadlock.
static BluetoothGattInterface* Get();
+ // Add or remove an observer that is interested in LE scanner interface
+ // notifications from us. Thread-safety is guaranteed by ObserverList.
+ virtual void AddScannerObserver(ScannerObserver* observer) = 0;
+ virtual void RemoveScannerObserver(ScannerObserver* observer) = 0;
+
// Add or remove an observer that is interested in GATT client interface
// notifications from us. Thread-safety is guaranteed by ObserverList.
virtual void AddClientObserver(ClientObserver* observer) = 0;
@@ -247,6 +264,14 @@
// structure.
virtual BleAdvertiserInterface* GetAdvertiserHALInterface() const = 0;
+ // The HAL module pointer that represents the standard BT LE scanner
+ // interface. This is implemented in and provided by the shared Bluetooth
+ // library, so this isn't owned by us.
+ //
+ // Upper layers can make ble_scanner_interface_t API calls through this
+ // structure.
+ virtual const btgatt_scanner_interface_t* GetScannerHALInterface() const = 0;
+
// The HAL module pointer that represents the standard BT-GATT client
// interface. This is implemented in and provided by the shared Bluetooth
// library, so this isn't owned by us.
diff --git a/service/hal/fake_bluetooth_gatt_interface.cc b/service/hal/fake_bluetooth_gatt_interface.cc
index b19a216..56b7514 100644
--- a/service/hal/fake_bluetooth_gatt_interface.cc
+++ b/service/hal/fake_bluetooth_gatt_interface.cc
@@ -24,6 +24,7 @@
// interface methods all have to be global and their signatures don't allow us
// to pass in user_data.
std::shared_ptr<BleAdvertiserInterface> g_advertiser_handler;
+std::shared_ptr<FakeBluetoothGattInterface::TestScannerHandler> g_scanner_handler;
std::shared_ptr<FakeBluetoothGattInterface::TestClientHandler> g_client_handler;
std::shared_ptr<FakeBluetoothGattInterface::TestServerHandler> g_server_handler;
@@ -42,22 +43,22 @@
}
bt_status_t FakeRegisterScanner(bt_uuid_t* app_uuid) {
- if (g_client_handler)
- return g_client_handler->RegisterClient(app_uuid);
+ if (g_scanner_handler)
+ return g_scanner_handler->RegisterScanner(app_uuid);
return BT_STATUS_FAIL;
}
bt_status_t FakeUnregisterScanner(int client_if) {
- if (g_client_handler)
- return g_client_handler->UnregisterClient(client_if);
+ if (g_scanner_handler)
+ return g_scanner_handler->UnregisterScanner(client_if);
return BT_STATUS_FAIL;
}
bt_status_t FakeScan(bool start) {
- if (g_client_handler)
- return g_client_handler->Scan(start);
+ if (g_scanner_handler)
+ return g_scanner_handler->Scan(start);
return BT_STATUS_FAIL;
}
@@ -125,12 +126,24 @@
return BT_STATUS_FAIL;
}
-btgatt_client_interface_t fake_btgattc_iface = {
- FakeRegisterClient,
- FakeUnregisterClient,
+btgatt_scanner_interface_t fake_scanner_iface = {
FakeRegisterScanner,
FakeUnregisterScanner,
FakeScan,
+ nullptr, // scan_filter_param_setup
+ nullptr, // scan_filter_add_remove
+ nullptr, // scan_filter_clear
+ nullptr, // scan_filter_enable
+ nullptr, // set_scan_parameters
+ nullptr, // batchscan_cfg_storate
+ nullptr, // batchscan_enb_batch_scan
+ nullptr, // batchscan_dis_batch_scan
+ nullptr, // batchscan_read_reports
+};
+
+btgatt_client_interface_t fake_btgattc_iface = {
+ FakeRegisterClient,
+ FakeUnregisterClient,
FakeConnect,
FakeDisconnect,
nullptr, // listen
@@ -144,18 +157,9 @@
nullptr, // register_for_notification
nullptr, // deregister_for_notification
nullptr, // read_remote_rssi
- nullptr, // scan_filter_param_setup
- nullptr, // scan_filter_add_remove
- nullptr, // scan_filter_clear
- nullptr, // scan_filter_enable
nullptr, // get_device_type
nullptr, // configure_mtu
nullptr, // conn_parameter_update
- nullptr, // set_scan_parameters
- nullptr, // batchscan_cfg_storate
- nullptr, // batchscan_enb_batch_scan
- nullptr, // batchscan_dis_batch_scan
- nullptr, // batchscan_read_reports
nullptr, // test_command
nullptr, // get_gatt_db
};
@@ -176,10 +180,12 @@
FakeBluetoothGattInterface::FakeBluetoothGattInterface(
std::shared_ptr<BleAdvertiserInterface> advertiser_handler,
+ std::shared_ptr<TestScannerHandler> scanner_handler,
std::shared_ptr<TestClientHandler> client_handler,
std::shared_ptr<TestServerHandler> server_handler)
: client_handler_(client_handler) {
CHECK(!g_advertiser_handler);
+ CHECK(!g_scanner_handler);
CHECK(!g_client_handler);
CHECK(!g_server_handler);
@@ -187,6 +193,9 @@
if (advertiser_handler)
g_advertiser_handler = advertiser_handler;
+ if (scanner_handler)
+ g_scanner_handler = scanner_handler;
+
if (client_handler)
g_client_handler = client_handler;
@@ -198,6 +207,9 @@
if (g_advertiser_handler)
g_advertiser_handler = nullptr;
+ if (g_scanner_handler)
+ g_scanner_handler = nullptr;
+
if (g_client_handler)
g_client_handler = nullptr;
@@ -207,6 +219,19 @@
// The methods below can be used to notify observers with certain events and
// given parameters.
+void FakeBluetoothGattInterface::NotifyRegisterScannerCallback(
+ int status, int client_if,
+ const bt_uuid_t& app_uuid) {
+ FOR_EACH_OBSERVER(ScannerObserver, scanner_observers_,
+ RegisterScannerCallback(this, status, client_if, app_uuid));
+}
+
+void FakeBluetoothGattInterface::NotifyScanResultCallback(
+ const bt_bdaddr_t& bda, int rssi, vector<uint8_t> adv_data) {
+ FOR_EACH_OBSERVER(ScannerObserver, scanner_observers_,
+ ScanResultCallback(this, bda, rssi, adv_data));
+}
+
void FakeBluetoothGattInterface::NotifyRegisterClientCallback(
int status, int client_if,
const bt_uuid_t& app_uuid) {
@@ -226,12 +251,6 @@
DisconnectCallback(this, conn_id, status, client_if, bda));
}
-void FakeBluetoothGattInterface::NotifyScanResultCallback(
- const bt_bdaddr_t& bda, int rssi, vector<uint8_t> adv_data) {
- FOR_EACH_OBSERVER(ClientObserver, client_observers_,
- ScanResultCallback(this, bda, rssi, adv_data));
-}
-
void FakeBluetoothGattInterface::NotifyRegisterServerCallback(
int status, int server_if,
const bt_uuid_t& app_uuid) {
@@ -307,6 +326,17 @@
IndicationSentCallback(this, conn_id, status));
}
+void FakeBluetoothGattInterface::AddScannerObserver(ScannerObserver* observer) {
+ CHECK(observer);
+ scanner_observers_.AddObserver(observer);
+}
+
+void FakeBluetoothGattInterface::RemoveScannerObserver(
+ ScannerObserver* observer) {
+ CHECK(observer);
+ scanner_observers_.RemoveObserver(observer);
+}
+
void FakeBluetoothGattInterface::AddClientObserver(ClientObserver* observer) {
CHECK(observer);
client_observers_.AddObserver(observer);
@@ -334,6 +364,12 @@
return g_advertiser_handler.get();
}
+const btgatt_scanner_interface_t*
+FakeBluetoothGattInterface::GetScannerHALInterface() const {
+ return &fake_scanner_iface;
+}
+
+
const btgatt_client_interface_t*
FakeBluetoothGattInterface::GetClientHALInterface() const {
return &fake_btgattc_iface;
diff --git a/service/hal/fake_bluetooth_gatt_interface.h b/service/hal/fake_bluetooth_gatt_interface.h
index 06c9109..363e053 100644
--- a/service/hal/fake_bluetooth_gatt_interface.h
+++ b/service/hal/fake_bluetooth_gatt_interface.h
@@ -27,6 +27,19 @@
class FakeBluetoothGattInterface : public BluetoothGattInterface {
public:
+ // Handles HAL LE scanner API calls for testing. Test code can
+ // provide a fake or mock implementation of this and all calls will be routed
+ // to it.
+ class TestScannerHandler {
+ public:
+ virtual ~TestScannerHandler() = default;
+
+ virtual bt_status_t RegisterScanner(bt_uuid_t* app_uuid) = 0;
+ virtual bt_status_t UnregisterScanner(int client_if) = 0;
+
+ virtual bt_status_t Scan(bool start) = 0;
+ };
+
// Handles HAL Bluetooth GATT client API calls for testing. Test code can
// provide a fake or mock implementation of this and all calls will be routed
// to it.
@@ -37,7 +50,6 @@
virtual bt_status_t RegisterClient(bt_uuid_t* app_uuid) = 0;
virtual bt_status_t UnregisterClient(int client_if) = 0;
- virtual bt_status_t Scan(bool start) = 0;
virtual bt_status_t Connect(int client_if, const bt_bdaddr_t *bd_addr,
bool is_direct, int transport) = 0;
virtual bt_status_t Disconnect(int client_if, const bt_bdaddr_t *bd_addr,
@@ -67,6 +79,7 @@
// provide their own handlers or simply pass "nullptr" for the default
// behavior in which BT_STATUS_FAIL will be returned from all calls.
FakeBluetoothGattInterface(std::shared_ptr<BleAdvertiserInterface> advertiser_handler,
+ std::shared_ptr<TestScannerHandler> scanner_handler,
std::shared_ptr<TestClientHandler> client_handler,
std::shared_ptr<TestServerHandler> server_handler);
~FakeBluetoothGattInterface();
@@ -74,6 +87,11 @@
// The methods below can be used to notify observers with certain events and
// given parameters.
+ void NotifyRegisterScannerCallback(int status, int client_if,
+ const bt_uuid_t& app_uuid);
+ void NotifyScanResultCallback(const bt_bdaddr_t& bda, int rssi,
+ vector<uint8_t> adv_data);
+
// Client callbacks:
void NotifyRegisterClientCallback(int status, int client_if,
const bt_uuid_t& app_uuid);
@@ -81,8 +99,6 @@
const bt_bdaddr_t& bda);
void NotifyDisconnectCallback(int conn_id, int status, int client_if,
const bt_bdaddr_t& bda);
- void NotifyScanResultCallback(const bt_bdaddr_t& bda, int rssi,
- vector<uint8_t> adv_data);
// Server callbacks:
void NotifyRegisterServerCallback(int status, int server_if,
@@ -118,17 +134,22 @@
void NotifyIndicationSentCallback(int conn_id, int status);
// BluetoothGattInterface overrides:
+ void AddScannerObserver(ScannerObserver* observer) override;
+ void RemoveScannerObserver(ScannerObserver* observer) override;
void AddClientObserver(ClientObserver* observer) override;
void RemoveClientObserver(ClientObserver* observer) override;
void AddServerObserver(ServerObserver* observer) override;
void RemoveServerObserver(ServerObserver* observer) override;
BleAdvertiserInterface* GetAdvertiserHALInterface() const override;
+ const btgatt_scanner_interface_t* GetScannerHALInterface() const override;
const btgatt_client_interface_t* GetClientHALInterface() const override;
const btgatt_server_interface_t* GetServerHALInterface() const override;
private:
+ base::ObserverList<ScannerObserver> scanner_observers_;
base::ObserverList<ClientObserver> client_observers_;
base::ObserverList<ServerObserver> server_observers_;
+ std::shared_ptr<TestScannerHandler> scanner_handler_;
std::shared_ptr<TestClientHandler> client_handler_;
std::shared_ptr<TestServerHandler> server_handler_;
diff --git a/service/ipc/binder/bluetooth_binder_server.cc b/service/ipc/binder/bluetooth_binder_server.cc
index 9d1db8b..953f974 100644
--- a/service/ipc/binder/bluetooth_binder_server.cc
+++ b/service/ipc/binder/bluetooth_binder_server.cc
@@ -22,6 +22,7 @@
#include "service/ipc/binder/bluetooth_gatt_server_binder_server.h"
#include "service/ipc/binder/bluetooth_low_energy_binder_server.h"
#include "service/ipc/binder/bluetooth_le_advertiser_binder_server.h"
+#include "service/ipc/binder/bluetooth_le_scanner_binder_server.h"
#include "service/hal/bluetooth_interface.h"
@@ -168,6 +169,23 @@
return Status::ok();
}
+Status BluetoothBinderServer::GetLeScannerInterface(
+ ::android::sp<IBluetoothLeScanner>* _aidl_return) {
+ VLOG(2) << __func__;
+
+ if (!adapter_->IsEnabled()) {
+ LOG(ERROR) << "Cannot obtain IBluetoothLeScanner interface while disabled";
+ *_aidl_return = NULL;
+ return Status::ok();
+ }
+
+ if (!le_scanner_interface_.get())
+ le_scanner_interface_ = new BluetoothLeScannerBinderServer(adapter_);
+
+ *_aidl_return = le_scanner_interface_;
+ return Status::ok();
+}
+
Status BluetoothBinderServer::GetGattClientInterface(
::android::sp<IBluetoothGattClient>* _aidl_return) {
VLOG(2) << __func__;
diff --git a/service/ipc/binder/bluetooth_binder_server.h b/service/ipc/binder/bluetooth_binder_server.h
index 3e9ed41..5bb794e 100644
--- a/service/ipc/binder/bluetooth_binder_server.h
+++ b/service/ipc/binder/bluetooth_binder_server.h
@@ -29,6 +29,7 @@
#include <android/bluetooth/IBluetoothGattServer.h>
#include <android/bluetooth/IBluetoothLowEnergy.h>
#include <android/bluetooth/IBluetoothLeAdvertiser.h>
+#include <android/bluetooth/IBluetoothLeScanner.h>
#include "service/adapter.h"
#include "service/common/bluetooth/uuid.h"
@@ -43,6 +44,7 @@
using android::bluetooth::IBluetoothGattServer;
using android::bluetooth::IBluetoothLowEnergy;
using android::bluetooth::IBluetoothLeAdvertiser;
+using android::bluetooth::IBluetoothLeScanner;
namespace ipc {
namespace binder {
@@ -76,6 +78,8 @@
::android::sp<IBluetoothLowEnergy>* _aidl_return) override;
Status GetLeAdvertiserInterface(
::android::sp<IBluetoothLeAdvertiser>* _aidl_return) override;
+ Status GetLeScannerInterface(
+ ::android::sp<IBluetoothLeScanner>* _aidl_return) override;
Status GetGattClientInterface(
::android::sp<IBluetoothGattClient>* _aidl_return) override;
Status GetGattServerInterface(
@@ -101,6 +105,10 @@
// first call to GetLeAdvertiserInterface().
android::sp<IBluetoothLeAdvertiser> le_advertiser_interface_;
+ // The IBluetoothLeScanner interface handle. This is lazily initialized on the
+ // first call to GetLeScannerInterface().
+ android::sp<IBluetoothLeScanner> le_scanner_interface_;
+
// The IBluetoothGattClient interface handle. This is lazily initialized on
// the first call to GetGattClientInterface().
android::sp<IBluetoothGattClient> gatt_client_interface_;
diff --git a/service/ipc/binder/bluetooth_le_scanner_binder_server.cc b/service/ipc/binder/bluetooth_le_scanner_binder_server.cc
new file mode 100644
index 0000000..e65ed06
--- /dev/null
+++ b/service/ipc/binder/bluetooth_le_scanner_binder_server.cc
@@ -0,0 +1,148 @@
+//
+// 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.
+//
+
+#include "service/ipc/binder/bluetooth_le_scanner_binder_server.h"
+
+#include <base/logging.h>
+
+#include "service/adapter.h"
+
+using android::String8;
+using android::String16;
+using android::binder::Status;
+
+namespace ipc {
+namespace binder {
+
+namespace {
+const int kInvalidInstanceId = -1;
+} // namespace
+
+BluetoothLeScannerBinderServer::BluetoothLeScannerBinderServer(
+ bluetooth::Adapter* adapter)
+ : adapter_(adapter) {
+ CHECK(adapter_);
+}
+
+BluetoothLeScannerBinderServer::~BluetoothLeScannerBinderServer() {}
+
+Status BluetoothLeScannerBinderServer::RegisterScanner(
+ const android::sp<IBluetoothLeScannerCallback>& callback,
+ bool* _aidl_return) {
+ VLOG(2) << __func__;
+ bluetooth::LowEnergyScannerFactory* ble_factory =
+ adapter_->GetLeScannerFactory();
+
+ *_aidl_return = RegisterInstanceBase(callback, ble_factory);
+ return Status::ok();
+}
+
+Status BluetoothLeScannerBinderServer::UnregisterScanner(int scanner_id) {
+ VLOG(2) << __func__;
+ UnregisterInstanceBase(scanner_id);
+ return Status::ok();
+}
+
+Status BluetoothLeScannerBinderServer::UnregisterAll() {
+ VLOG(2) << __func__;
+ UnregisterAllBase();
+ return Status::ok();
+}
+
+Status BluetoothLeScannerBinderServer::StartScan(
+ int scanner_id, const android::bluetooth::ScanSettings& settings,
+ const std::vector<android::bluetooth::ScanFilter>& filters,
+ bool* _aidl_return) {
+ VLOG(2) << __func__ << " scanner_id: " << scanner_id;
+ std::lock_guard<std::mutex> lock(*maps_lock());
+
+ auto scanner = GetLEScanner(scanner_id);
+ if (!scanner) {
+ LOG(ERROR) << "Unknown scanner_id: " << scanner_id;
+ *_aidl_return = false;
+ return Status::ok();
+ }
+
+ std::vector<bluetooth::ScanFilter> flt;
+ for (const auto& filter : filters) {
+ flt.push_back(filter);
+ }
+
+ *_aidl_return = scanner->StartScan(settings, flt);
+ return Status::ok();
+}
+
+Status BluetoothLeScannerBinderServer::StopScan(int scanner_id,
+ bool* _aidl_return) {
+ VLOG(2) << __func__ << " scanner_id: " << scanner_id;
+ std::lock_guard<std::mutex> lock(*maps_lock());
+
+ auto scanner = GetLEScanner(scanner_id);
+ if (!scanner) {
+ LOG(ERROR) << "Unknown scanner_id: " << scanner_id;
+ *_aidl_return = false;
+ return Status::ok();
+ }
+
+ *_aidl_return = scanner->StopScan();
+ return Status::ok();
+}
+
+void BluetoothLeScannerBinderServer::OnScanResult(
+ bluetooth::LowEnergyScanner* scanner, const bluetooth::ScanResult& result) {
+ VLOG(2) << __func__;
+ std::lock_guard<std::mutex> lock(*maps_lock());
+
+ int scanner_id = scanner->GetInstanceId();
+ auto cb = GetLECallback(scanner->GetInstanceId());
+ if (!cb.get()) {
+ VLOG(2) << "Scanner was unregistered - scanner_id: " << scanner_id;
+ return;
+ }
+
+ cb->OnScanResult(result);
+}
+
+android::sp<IBluetoothLeScannerCallback>
+BluetoothLeScannerBinderServer::GetLECallback(int scanner_id) {
+ auto cb = GetCallback(scanner_id);
+ return android::sp<IBluetoothLeScannerCallback>(
+ static_cast<IBluetoothLeScannerCallback*>(cb.get()));
+}
+
+std::shared_ptr<bluetooth::LowEnergyScanner>
+BluetoothLeScannerBinderServer::GetLEScanner(int scanner_id) {
+ return std::static_pointer_cast<bluetooth::LowEnergyScanner>(
+ GetInstance(scanner_id));
+}
+
+void BluetoothLeScannerBinderServer::OnRegisterInstanceImpl(
+ bluetooth::BLEStatus status, android::sp<IInterface> callback,
+ bluetooth::BluetoothInstance* instance) {
+ VLOG(1) << __func__ << " status: " << status;
+ bluetooth::LowEnergyScanner* le_scanner =
+ static_cast<bluetooth::LowEnergyScanner*>(instance);
+ le_scanner->SetDelegate(this);
+
+ android::sp<IBluetoothLeScannerCallback> cb(
+ static_cast<IBluetoothLeScannerCallback*>(callback.get()));
+ cb->OnScannerRegistered(status, (status == bluetooth::BLE_STATUS_SUCCESS)
+ ? instance->GetInstanceId()
+ : kInvalidInstanceId);
+}
+
+} // namespace binder
+} // namespace ipc
diff --git a/service/ipc/binder/bluetooth_le_scanner_binder_server.h b/service/ipc/binder/bluetooth_le_scanner_binder_server.h
new file mode 100644
index 0000000..655c91b
--- /dev/null
+++ b/service/ipc/binder/bluetooth_le_scanner_binder_server.h
@@ -0,0 +1,86 @@
+//
+// 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.
+//
+
+#pragma once
+
+#include <memory>
+
+#include <base/macros.h>
+
+#include <android/bluetooth/IBluetoothLeScannerCallback.h>
+#include "android/bluetooth/BnBluetoothLeScanner.h"
+
+#include "service/common/bluetooth/low_energy_constants.h"
+#include "service/ipc/binder/interface_with_instances_base.h"
+#include "service/low_energy_scanner.h"
+
+using android::binder::Status;
+using android::String16;
+
+using android::bluetooth::BnBluetoothLeScanner;
+using android::bluetooth::IBluetoothLeScannerCallback;
+
+namespace bluetooth {
+class Adapter;
+} // namespace bluetooth
+
+namespace ipc {
+namespace binder {
+
+// Implements the server side of the IBluetoothLowEnergy interface.
+class BluetoothLeScannerBinderServer
+ : public BnBluetoothLeScanner,
+ public InterfaceWithInstancesBase,
+ public bluetooth::LowEnergyScanner::Delegate {
+ public:
+ explicit BluetoothLeScannerBinderServer(bluetooth::Adapter* adapter);
+ ~BluetoothLeScannerBinderServer() override;
+
+ // IBluetoothLowEnergy overrides:
+ Status RegisterScanner(
+ const android::sp<IBluetoothLeScannerCallback>& callback,
+ bool* _aidl_return) override;
+ Status UnregisterScanner(int scanner_id) override;
+ Status UnregisterAll() override;
+ Status StartScan(int scanner_id,
+ const android::bluetooth::ScanSettings& settings,
+ const std::vector<android::bluetooth::ScanFilter>& filters,
+ bool* _aidl_return) override;
+ Status StopScan(int scanner_id, bool* _aidl_return) override;
+
+ void OnScanResult(bluetooth::LowEnergyScanner* scanner,
+ const bluetooth::ScanResult& result) override;
+ private:
+ // Returns a pointer to the IBluetoothLowEnergyCallback instance associated
+ // with |scanner_id|. Returns NULL if such a callback cannot be found.
+ android::sp<IBluetoothLeScannerCallback> GetLECallback(int scanner_id);
+
+ // Returns a pointer to the LowEnergyScanner instance associated with
+ // |scanner_id|. Returns NULL if such a scanner cannot be found.
+ std::shared_ptr<bluetooth::LowEnergyScanner> GetLEScanner(int scanner_id);
+
+ // InterfaceWithInstancesBase override:
+ void OnRegisterInstanceImpl(bluetooth::BLEStatus status,
+ android::sp<IInterface> callback,
+ bluetooth::BluetoothInstance* instance) override;
+
+ bluetooth::Adapter* adapter_; // weak
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothLeScannerBinderServer);
+};
+
+} // namespace binder
+} // namespace ipc
diff --git a/service/ipc/binder/bluetooth_low_energy_binder_server.cc b/service/ipc/binder/bluetooth_low_energy_binder_server.cc
index d86072a..9b8a863 100644
--- a/service/ipc/binder/bluetooth_low_energy_binder_server.cc
+++ b/service/ipc/binder/bluetooth_low_energy_binder_server.cc
@@ -117,45 +117,6 @@
return Status::ok();
}
-Status BluetoothLowEnergyBinderServer::StartScan(
- int client_id, const android::bluetooth::ScanSettings& settings,
- const std::vector<android::bluetooth::ScanFilter>& filters,
- bool* _aidl_return) {
- VLOG(2) << __func__ << " client_id: " << client_id;
- std::lock_guard<std::mutex> lock(*maps_lock());
-
- auto client = GetLEClient(client_id);
- if (!client) {
- LOG(ERROR) << "Unknown client_id: " << client_id;
- *_aidl_return = false;
- return Status::ok();
- }
-
- std::vector<bluetooth::ScanFilter> flt;
- for (const auto& filter : filters) {
- flt.push_back(filter);
- }
-
- *_aidl_return = client->StartScan(settings, flt);
- return Status::ok();
-}
-
-Status BluetoothLowEnergyBinderServer::StopScan(int client_id,
- bool* _aidl_return) {
- VLOG(2) << __func__ << " client_id: " << client_id;
- std::lock_guard<std::mutex> lock(*maps_lock());
-
- auto client = GetLEClient(client_id);
- if (!client) {
- LOG(ERROR) << "Unknown client_id: " << client_id;
- *_aidl_return = false;
- return Status::ok();
- }
-
- *_aidl_return = client->StopScan();
- return Status::ok();
-}
-
void BluetoothLowEnergyBinderServer::OnConnectionState(
bluetooth::LowEnergyClient* client, int status, const char* address,
bool connected) {
@@ -188,21 +149,6 @@
cb->OnMtuChanged(status, String16(address, std::strlen(address)), mtu);
}
-void BluetoothLowEnergyBinderServer::OnScanResult(
- bluetooth::LowEnergyClient* client, const bluetooth::ScanResult& result) {
- VLOG(2) << __func__;
- std::lock_guard<std::mutex> lock(*maps_lock());
-
- int client_id = client->GetInstanceId();
- auto cb = GetLECallback(client->GetInstanceId());
- if (!cb.get()) {
- VLOG(2) << "Client was unregistered - client_id: " << client_id;
- return;
- }
-
- cb->OnScanResult(result);
-}
-
android::sp<IBluetoothLowEnergyCallback>
BluetoothLowEnergyBinderServer::GetLECallback(int client_id) {
auto cb = GetCallback(client_id);
diff --git a/service/ipc/binder/bluetooth_low_energy_binder_server.h b/service/ipc/binder/bluetooth_low_energy_binder_server.h
index 8b53a71..d393c7d 100644
--- a/service/ipc/binder/bluetooth_low_energy_binder_server.h
+++ b/service/ipc/binder/bluetooth_low_energy_binder_server.h
@@ -61,19 +61,12 @@
bool* _aidl_return) override;
Status SetMtu(int client_id, const String16& address, int mtu,
bool* _aidl_return) override;
- Status StartScan(int client_id,
- const android::bluetooth::ScanSettings& settings,
- const std::vector<android::bluetooth::ScanFilter>& filters,
- bool* _aidl_return) override;
- Status StopScan(int client_id, bool* _aidl_return) override;
// bluetooth::LowEnergyClient::Delegate overrides:
void OnConnectionState(bluetooth::LowEnergyClient* client, int status,
const char* address, bool connected) override;
void OnMtuChanged(bluetooth::LowEnergyClient* client, int status,
const char* address, int mtu) override;
- void OnScanResult(bluetooth::LowEnergyClient* client,
- const bluetooth::ScanResult& result) override;
private:
// Returns a pointer to the IBluetoothLowEnergyCallback instance associated
diff --git a/service/low_energy_client.cc b/service/low_energy_client.cc
index fe7ea76..3fce035 100644
--- a/service/low_energy_client.cc
+++ b/service/low_energy_client.cc
@@ -29,40 +29,6 @@
namespace bluetooth {
-namespace {
-
-// 31 + 31 for advertising data and scan response. This is the maximum length
-// TODO(armansito): Fix the HAL to return a concatenated blob that contains the
-// true length of each field and also provide a length parameter so that we
-// can support advertising length extensions in the future.
-const size_t kScanRecordLength = 62;
-
-// Returns the length of the given scan record array. We have to calculate this
-// based on the maximum possible data length and the TLV data. See TODO above
-// |kScanRecordLength|.
-size_t GetScanRecordLength(vector<uint8_t> bytes) {
- for (size_t i = 0, field_len = 0; i < kScanRecordLength;
- i += (field_len + 1)) {
- field_len = bytes[i];
-
- // Assert here that the data returned from the stack is correctly formatted
- // in TLV form and that the length of the current field won't exceed the
- // total data length.
- CHECK(i + field_len < kScanRecordLength);
-
- // If the field length is zero and we haven't reached the maximum length,
- // then we have found the length, as the stack will pad the data with zeros
- // accordingly.
- if (field_len == 0)
- return i;
- }
-
- // We have reached the end.
- return kScanRecordLength;
-}
-
-} // namespace
-
// LowEnergyClient implementation
// ========================================================
@@ -71,7 +37,6 @@
: adapter_(adapter),
app_identifier_(uuid),
client_id_(client_id),
- scan_started_(false),
delegate_(nullptr) {
}
@@ -84,10 +49,6 @@
hal::BluetoothGattInterface::Get()->
GetClientHALInterface()->unregister_client(client_id_);
-
- // Stop any scans started by this client.
- if (scan_started_.load())
- StopScan();
}
bool LowEnergyClient::Connect(const std::string& address, bool is_direct) {
@@ -165,45 +126,6 @@
delegate_ = delegate;
}
-bool LowEnergyClient::StartScan(const ScanSettings& settings,
- const std::vector<ScanFilter>& filters) {
- VLOG(2) << __func__;
-
- // Cannot start a scan if the adapter is not enabled.
- if (!adapter_.IsEnabled()) {
- LOG(ERROR) << "Cannot scan while Bluetooth is disabled";
- return false;
- }
-
- // TODO(jpawlowski): Push settings and filtering logic below the HAL.
- bt_status_t status = hal::BluetoothGattInterface::Get()->
- StartScan(client_id_);
- if (status != BT_STATUS_SUCCESS) {
- LOG(ERROR) << "Failed to initiate scanning for client: " << client_id_;
- return false;
- }
-
- scan_started_ = true;
- return true;
-}
-
-bool LowEnergyClient::StopScan() {
- VLOG(2) << __func__;
-
- // TODO(armansito): We don't support batch scanning yet so call
- // StopRegularScanForClient directly. In the future we will need to
- // conditionally call a batch scan API here.
- bt_status_t status = hal::BluetoothGattInterface::Get()->
- StopScan(client_id_);
- if (status != BT_STATUS_SUCCESS) {
- LOG(ERROR) << "Failed to stop scan for client: " << client_id_;
- return false;
- }
-
- scan_started_ = false;
- return true;
-}
-
const UUID& LowEnergyClient::GetAppIdentifier() const {
return app_identifier_;
}
@@ -212,27 +134,6 @@
return client_id_;
}
-void LowEnergyClient::ScanResultCallback(
- hal::BluetoothGattInterface* gatt_iface,
- const bt_bdaddr_t& bda, int rssi, vector<uint8_t> adv_data) {
- // Ignore scan results if this client didn't start a scan.
- if (!scan_started_.load())
- return;
-
- lock_guard<mutex> lock(delegate_mutex_);
- if (!delegate_)
- return;
-
- // TODO(armansito): Apply software filters here.
-
- size_t record_len = GetScanRecordLength(adv_data);
- std::vector<uint8_t> scan_record(adv_data.begin(), adv_data.begin() + record_len);
-
- ScanResult result(BtAddrString(&bda), scan_record, rssi);
-
- delegate_->OnScanResult(this, result);
-}
-
void LowEnergyClient::ConnectCallback(
hal::BluetoothGattInterface* gatt_iface, int conn_id, int status,
int client_id, const bt_bdaddr_t& bda) {
diff --git a/service/low_energy_client.h b/service/low_energy_client.h
index 5afc0f2..b8e4fec 100644
--- a/service/low_energy_client.h
+++ b/service/low_energy_client.h
@@ -54,11 +54,6 @@
Delegate() = default;
virtual ~Delegate() = default;
- // Called asynchronously to notify the delegate of nearby BLE advertisers
- // found during a device scan.
- virtual void OnScanResult(LowEnergyClient* client,
- const ScanResult& scan_result) = 0;
-
// Called asynchronously to notify the delegate of connection state change
virtual void OnConnectionState(LowEnergyClient* client, int status,
const char* address, bool connected) = 0;
@@ -95,19 +90,6 @@
// Return true on success, false otherwise.
bool SetMtu(const std::string& address, int mtu);
- // Initiates a BLE device scan for this client using the given |settings| and
- // |filters|. See the documentation for ScanSettings and ScanFilter for how
- // these parameters can be configured. Return true on success, false
- // otherwise. Please see logs for details in case of error.
- bool StartScan(const ScanSettings& settings,
- const std::vector<ScanFilter>& filters);
-
- // Stops an ongoing BLE device scan for this client.
- bool StopScan();
-
- // Returns the current scan settings.
- const ScanSettings& scan_settings() const { return scan_settings_; }
-
// BluetoothClientInstace overrides:
const UUID& GetAppIdentifier() const override;
int GetInstanceId() const override;
@@ -120,11 +102,6 @@
LowEnergyClient(Adapter& adapter, const UUID& uuid, int client_id);
// BluetoothGattInterface::ClientObserver overrides:
- void ScanResultCallback(
- hal::BluetoothGattInterface* gatt_iface,
- const bt_bdaddr_t& bda, int rssi,
- vector<uint8_t> adv_data) override;
-
void ConnectCallback(
hal::BluetoothGattInterface* gatt_iface, int conn_id, int status,
int client_id, const bt_bdaddr_t& bda) override;
@@ -146,15 +123,6 @@
UUID app_identifier_;
int client_id_;
- // Protects device scan related members below.
- std::mutex scan_fields_lock_;
-
- // Current scan settings.
- ScanSettings scan_settings_;
-
- // If true, then this client have a BLE device scan in progress.
- std::atomic_bool scan_started_;
-
// Raw handle to the Delegate, which must outlive this LowEnergyClient
// instance.
std::mutex delegate_mutex_;
diff --git a/service/low_energy_scanner.cc b/service/low_energy_scanner.cc
new file mode 100644
index 0000000..c865e9b
--- /dev/null
+++ b/service/low_energy_scanner.cc
@@ -0,0 +1,234 @@
+//
+// 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.
+//
+
+#include "service/low_energy_scanner.h"
+
+#include <base/bind.h>
+#include <base/logging.h>
+
+#include "service/adapter.h"
+#include "service/common/bluetooth/util/address_helper.h"
+#include "service/logging_helpers.h"
+#include "stack/include/bt_types.h"
+#include "stack/include/hcidefs.h"
+
+using std::lock_guard;
+using std::mutex;
+
+namespace bluetooth {
+
+namespace {
+
+// 31 + 31 for advertising data and scan response. This is the maximum length
+// TODO(armansito): Fix the HAL to return a concatenated blob that contains the
+// true length of each field and also provide a length parameter so that we
+// can support advertising length extensions in the future.
+const size_t kScanRecordLength = 62;
+
+// Returns the length of the given scan record array. We have to calculate this
+// based on the maximum possible data length and the TLV data. See TODO above
+// |kScanRecordLength|.
+size_t GetScanRecordLength(vector<uint8_t> bytes) {
+ for (size_t i = 0, field_len = 0; i < kScanRecordLength;
+ i += (field_len + 1)) {
+ field_len = bytes[i];
+
+ // Assert here that the data returned from the stack is correctly formatted
+ // in TLV form and that the length of the current field won't exceed the
+ // total data length.
+ CHECK(i + field_len < kScanRecordLength);
+
+ // If the field length is zero and we haven't reached the maximum length,
+ // then we have found the length, as the stack will pad the data with zeros
+ // accordingly.
+ if (field_len == 0)
+ return i;
+ }
+
+ // We have reached the end.
+ return kScanRecordLength;
+}
+
+} // namespace
+
+// LowEnergyScanner implementation
+// ========================================================
+
+LowEnergyScanner::LowEnergyScanner(Adapter& adapter, const UUID& uuid,
+ int scanner_id)
+ : adapter_(adapter),
+ app_identifier_(uuid),
+ scanner_id_(scanner_id),
+ scan_started_(false),
+ delegate_(nullptr) {}
+
+LowEnergyScanner::~LowEnergyScanner() {
+ // Automatically unregister the scanner.
+ VLOG(1) << "LowEnergyScanner unregistering scanner: " << scanner_id_;
+
+ // Unregister as observer so we no longer receive any callbacks.
+ hal::BluetoothGattInterface::Get()->RemoveScannerObserver(this);
+
+ hal::BluetoothGattInterface::Get()->
+ GetScannerHALInterface()->unregister_scanner(scanner_id_);
+
+ // Stop any scans started by this client.
+ if (scan_started_.load())
+ StopScan();
+}
+
+void LowEnergyScanner::SetDelegate(Delegate* delegate) {
+ lock_guard<mutex> lock(delegate_mutex_);
+ delegate_ = delegate;
+}
+
+bool LowEnergyScanner::StartScan(const ScanSettings& settings,
+ const std::vector<ScanFilter>& filters) {
+ VLOG(2) << __func__;
+
+ // Cannot start a scan if the adapter is not enabled.
+ if (!adapter_.IsEnabled()) {
+ LOG(ERROR) << "Cannot scan while Bluetooth is disabled";
+ return false;
+ }
+
+ // TODO(jpawlowski): Push settings and filtering logic below the HAL.
+ bt_status_t status = hal::BluetoothGattInterface::Get()->
+ StartScan(scanner_id_);
+ if (status != BT_STATUS_SUCCESS) {
+ LOG(ERROR) << "Failed to initiate scanning for client: " << scanner_id_;
+ return false;
+ }
+
+ scan_started_ = true;
+ return true;
+}
+
+bool LowEnergyScanner::StopScan() {
+ VLOG(2) << __func__;
+
+ // TODO(armansito): We don't support batch scanning yet so call
+ // StopRegularScanForClient directly. In the future we will need to
+ // conditionally call a batch scan API here.
+ bt_status_t status = hal::BluetoothGattInterface::Get()->
+ StopScan(scanner_id_);
+ if (status != BT_STATUS_SUCCESS) {
+ LOG(ERROR) << "Failed to stop scan for client: " << scanner_id_;
+ return false;
+ }
+
+ scan_started_ = false;
+ return true;
+}
+
+const UUID& LowEnergyScanner::GetAppIdentifier() const {
+ return app_identifier_;
+}
+
+int LowEnergyScanner::GetInstanceId() const {
+ return scanner_id_;
+}
+
+void LowEnergyScanner::ScanResultCallback(
+ hal::BluetoothGattInterface* gatt_iface,
+ const bt_bdaddr_t& bda, int rssi, vector<uint8_t> adv_data) {
+ // Ignore scan results if this client didn't start a scan.
+ if (!scan_started_.load())
+ return;
+
+ lock_guard<mutex> lock(delegate_mutex_);
+ if (!delegate_)
+ return;
+
+ // TODO(armansito): Apply software filters here.
+
+ size_t record_len = GetScanRecordLength(adv_data);
+ std::vector<uint8_t> scan_record(adv_data.begin(), adv_data.begin() + record_len);
+
+ ScanResult result(BtAddrString(&bda), scan_record, rssi);
+
+ delegate_->OnScanResult(this, result);
+}
+
+// LowEnergyScannerFactory implementation
+// ========================================================
+
+LowEnergyScannerFactory::LowEnergyScannerFactory(Adapter& adapter) : adapter_(adapter) {
+ hal::BluetoothGattInterface::Get()->AddScannerObserver(this);
+}
+
+LowEnergyScannerFactory::~LowEnergyScannerFactory() {
+ hal::BluetoothGattInterface::Get()->RemoveScannerObserver(this);
+}
+
+bool LowEnergyScannerFactory::RegisterInstance(
+ const UUID& uuid,
+ const RegisterCallback& callback) {
+ VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ lock_guard<mutex> lock(pending_calls_lock_);
+
+ if (pending_calls_.find(uuid) != pending_calls_.end()) {
+ LOG(ERROR) << "Low-Energy scanner with given UUID already registered - "
+ << "UUID: " << uuid.ToString();
+ return false;
+ }
+
+ const btgatt_scanner_interface_t* hal_iface =
+ hal::BluetoothGattInterface::Get()->GetScannerHALInterface();
+ bt_uuid_t app_uuid = uuid.GetBlueDroid();
+
+ if (hal_iface->register_scanner(&app_uuid) != BT_STATUS_SUCCESS)
+ return false;
+
+ pending_calls_[uuid] = callback;
+
+ return true;
+}
+
+void LowEnergyScannerFactory::RegisterScannerCallback(
+ hal::BluetoothGattInterface* gatt_iface,
+ int status, int scanner_id,
+ const bt_uuid_t& app_uuid) {
+ UUID uuid(app_uuid);
+
+ VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ lock_guard<mutex> lock(pending_calls_lock_);
+
+ auto iter = pending_calls_.find(uuid);
+ if (iter == pending_calls_.end()) {
+ VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
+ return;
+ }
+
+ // No need to construct a scanner if the call wasn't successful.
+ std::unique_ptr<LowEnergyScanner> scanner;
+ BLEStatus result = BLE_STATUS_FAILURE;
+ if (status == BT_STATUS_SUCCESS) {
+ scanner.reset(new LowEnergyScanner(adapter_, uuid, scanner_id));
+
+ gatt_iface->AddScannerObserver(scanner.get());
+
+ result = BLE_STATUS_SUCCESS;
+ }
+
+ // Notify the result via the result callback.
+ iter->second(result, uuid, std::move(scanner));
+
+ pending_calls_.erase(iter);
+}
+
+
+} // namespace bluetooth
diff --git a/service/low_energy_scanner.h b/service/low_energy_scanner.h
new file mode 100644
index 0000000..cae1f58
--- /dev/null
+++ b/service/low_energy_scanner.h
@@ -0,0 +1,160 @@
+//
+// 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.
+//
+
+#pragma once
+
+#include <atomic>
+#include <functional>
+#include <map>
+#include <mutex>
+
+#include <base/macros.h>
+
+#include "service/bluetooth_instance.h"
+#include "service/common/bluetooth/advertise_data.h"
+#include "service/common/bluetooth/advertise_settings.h"
+#include "service/common/bluetooth/low_energy_constants.h"
+#include "service/common/bluetooth/scan_filter.h"
+#include "service/common/bluetooth/scan_result.h"
+#include "service/common/bluetooth/scan_settings.h"
+#include "service/common/bluetooth/uuid.h"
+#include "service/hal/bluetooth_gatt_interface.h"
+
+namespace bluetooth {
+
+class Adapter;
+
+// A LowEnergyScanner represents an application's handle to perform various
+// Bluetooth Low Energy GAP operations. Instances cannot be created directly and
+// should be obtained through the factory.
+class LowEnergyScanner : private hal::BluetoothGattInterface::ScannerObserver,
+ public BluetoothInstance {
+ public:
+ // The Delegate interface is used to notify asynchronous events related to LE
+ // scan.
+ class Delegate {
+ public:
+ Delegate() = default;
+ virtual ~Delegate() = default;
+
+ // Called asynchronously to notify the delegate of nearby BLE advertisers
+ // found during a device scan.
+ virtual void OnScanResult(LowEnergyScanner* client,
+ const ScanResult& scan_result) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
+ };
+
+ // The destructor automatically unregisters this client instance from the
+ // stack.
+ ~LowEnergyScanner() override;
+
+ // Assigns a delegate to this instance. |delegate| must out-live this
+ // LowEnergyClient instance.
+ void SetDelegate(Delegate* delegate);
+
+ // Initiates a BLE device scan for this client using the given |settings| and
+ // |filters|. See the documentation for ScanSettings and ScanFilter for how
+ // these parameters can be configured. Return true on success, false
+ // otherwise. Please see logs for details in case of error.
+ bool StartScan(const ScanSettings& settings,
+ const std::vector<ScanFilter>& filters);
+
+ // Stops an ongoing BLE device scan for this client.
+ bool StopScan();
+
+ // Returns the current scan settings.
+ const ScanSettings& scan_settings() const { return scan_settings_; }
+
+ // BluetoothInstace overrides:
+ const UUID& GetAppIdentifier() const override;
+ int GetInstanceId() const override;
+
+ void ScanResultCallback(
+ hal::BluetoothGattInterface* gatt_iface,
+ const bt_bdaddr_t& bda, int rssi,
+ vector<uint8_t> adv_data) override;
+
+ private:
+ friend class LowEnergyScannerFactory;
+
+ // Constructor shouldn't be called directly as instances are meant to be
+ // obtained from the factory.
+ LowEnergyScanner(Adapter& adapter, const UUID& uuid, int scanner_id);
+
+ // Calls and clears the pending callbacks.
+ void InvokeAndClearStartCallback(BLEStatus status);
+ void InvokeAndClearStopCallback(BLEStatus status);
+
+ // Raw pointer to the Bluetooth Adapter.
+ Adapter& adapter_;
+
+ // See getters above for documentation.
+ UUID app_identifier_;
+ int scanner_id_;
+
+ // Protects device scan related members below.
+ std::mutex scan_fields_lock_;
+
+ // Current scan settings.
+ ScanSettings scan_settings_;
+
+ // If true, then this client have a BLE device scan in progress.
+ std::atomic_bool scan_started_;
+
+ // Raw handle to the Delegate, which must outlive this LowEnergyScanner
+ // instance.
+ std::mutex delegate_mutex_;
+ Delegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(LowEnergyScanner);
+};
+
+// LowEnergyScannerFactory is used to register and obtain a per-application
+// LowEnergyScanner instance. Users should call RegisterInstance to obtain their
+// own unique LowEnergyScanner instance that has been registered with the
+// Bluetooth stack.
+class LowEnergyScannerFactory
+ : private hal::BluetoothGattInterface::ScannerObserver,
+ public BluetoothInstanceFactory {
+ public:
+ // Don't construct/destruct directly except in tests. Instead, obtain a handle
+ // from an Adapter instance.
+ explicit LowEnergyScannerFactory(Adapter& adapter);
+ ~LowEnergyScannerFactory() override;
+
+ // BluetoothInstanceFactory override:
+ bool RegisterInstance(const UUID& app_uuid, const RegisterCallback& callback) override;
+
+ private:
+ friend class LowEnergyScanner;
+
+ // BluetoothGattInterface::ScannerObserver overrides:
+ void RegisterScannerCallback(hal::BluetoothGattInterface* gatt_iface, int status,
+ int scanner_id, const bt_uuid_t& app_uuid);
+
+ // Map of pending calls to register.
+ std::mutex pending_calls_lock_;
+ std::map<UUID, RegisterCallback> pending_calls_;
+
+ // Raw pointer to the Adapter that owns this factory.
+ Adapter& adapter_;
+
+ DISALLOW_COPY_AND_ASSIGN(LowEnergyScannerFactory);
+};
+
+} // namespace bluetooth
diff --git a/service/test/adapter_unittest.cc b/service/test/adapter_unittest.cc
index 706d4b9..ca64618 100644
--- a/service/test/adapter_unittest.cc
+++ b/service/test/adapter_unittest.cc
@@ -37,7 +37,7 @@
// Initialize GATT interface with default handlers.
hal::BluetoothGattInterface::InitializeForTesting(
- new hal::FakeBluetoothGattInterface(nullptr, nullptr, nullptr));
+ new hal::FakeBluetoothGattInterface(nullptr, nullptr, nullptr, nullptr));
adapter_ = Adapter::Create();
}
diff --git a/service/test/gatt_client_unittest.cc b/service/test/gatt_client_unittest.cc
index e4623bc..1628a7b 100644
--- a/service/test/gatt_client_unittest.cc
+++ b/service/test/gatt_client_unittest.cc
@@ -55,6 +55,7 @@
fake_hal_gatt_iface_ = new hal::FakeBluetoothGattInterface(
nullptr,
+ nullptr,
std::static_pointer_cast<
hal::FakeBluetoothGattInterface::TestClientHandler>(mock_handler_),
nullptr);
@@ -160,23 +161,5 @@
EXPECT_EQ(uuid1, cb_uuid);
}
-TEST_F(GattClientTest, StartStopScan) {
- EXPECT_CALL(*mock_handler_, Scan(true))
- .Times(1)
- .WillOnce(Return(BT_STATUS_SUCCESS));
-
- EXPECT_CALL(*mock_handler_, Scan(false))
- .Times(1)
- .WillOnce(Return(BT_STATUS_SUCCESS));
-
- for (int i = 0; i < 5; i++)
- hal::BluetoothGattInterface::Get()->StartScan(i);
-
- for (int i = 0; i < 5; i++)
- hal::BluetoothGattInterface::Get()->StopScan(i);
-
- testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
-}
-
} // namespace
} // namespace bluetooth
diff --git a/service/test/gatt_server_unittest.cc b/service/test/gatt_server_unittest.cc
index d73e186..ca4c2fe 100644
--- a/service/test/gatt_server_unittest.cc
+++ b/service/test/gatt_server_unittest.cc
@@ -175,6 +175,7 @@
fake_hal_gatt_iface_ = new hal::FakeBluetoothGattInterface(
nullptr,
nullptr,
+ nullptr,
std::static_pointer_cast<
hal::FakeBluetoothGattInterface::TestServerHandler>(mock_handler_));
diff --git a/service/test/ipc_linux_unittest.cc b/service/test/ipc_linux_unittest.cc
index b36fe75..efd50ac 100644
--- a/service/test/ipc_linux_unittest.cc
+++ b/service/test/ipc_linux_unittest.cc
@@ -59,7 +59,7 @@
bluetooth::hal::BluetoothInterface::InitializeForTesting(
new bluetooth::hal::FakeBluetoothInterface());
bluetooth::hal::BluetoothGattInterface::InitializeForTesting(
- new bluetooth::hal::FakeBluetoothGattInterface(nullptr, nullptr, nullptr));
+ new bluetooth::hal::FakeBluetoothGattInterface(nullptr, nullptr, nullptr, nullptr));
adapter_ = bluetooth::Adapter::Create();
ipc_manager_.reset(new ipc::IPCManager(adapter_.get()));
diff --git a/service/test/low_energy_advertiser_unittest.cc b/service/test/low_energy_advertiser_unittest.cc
index 43189b3..339c8c9 100644
--- a/service/test/low_energy_advertiser_unittest.cc
+++ b/service/test/low_energy_advertiser_unittest.cc
@@ -77,7 +77,7 @@
hal::BluetoothGattInterface::InitializeForTesting(
new hal::FakeBluetoothGattInterface(
std::static_pointer_cast<BleAdvertiserInterface>(mock_handler_),
- nullptr, nullptr));
+ nullptr, nullptr, nullptr));
ble_advertiser_factory_.reset(new LowEnergyAdvertiserFactory());
}
diff --git a/service/test/low_energy_client_unittest.cc b/service/test/low_energy_client_unittest.cc
index 31bbeed..1fc2393 100644
--- a/service/test/low_energy_client_unittest.cc
+++ b/service/test/low_energy_client_unittest.cc
@@ -37,15 +37,11 @@
class MockGattHandler
: public hal::FakeBluetoothGattInterface::TestClientHandler {
public:
- MockGattHandler() {
- ON_CALL(*this, Scan(false))
- .WillByDefault(Return(BT_STATUS_SUCCESS));
- }
+ MockGattHandler() {};
~MockGattHandler() override = default;
MOCK_METHOD1(RegisterClient, bt_status_t(bt_uuid_t*));
MOCK_METHOD1(UnregisterClient, bt_status_t(int));
- MOCK_METHOD1(Scan, bt_status_t(bool));
MOCK_METHOD4(Connect, bt_status_t(int , const bt_bdaddr_t *, bool, int));
MOCK_METHOD3(Disconnect, bt_status_t(int , const bt_bdaddr_t *, int));
@@ -55,15 +51,11 @@
class TestDelegate : public LowEnergyClient::Delegate {
public:
- TestDelegate() : scan_result_count_(0), connection_state_count_(0),
- last_mtu_(0) {
+ TestDelegate() : connection_state_count_(0), last_mtu_(0) {
}
~TestDelegate() override = default;
- int scan_result_count() const { return scan_result_count_; }
- const ScanResult& last_scan_result() const { return last_scan_result_; }
-
int connection_state_count() const { return connection_state_count_; }
void OnConnectionState(LowEnergyClient* client, int status,
@@ -78,16 +70,7 @@
last_mtu_ = mtu;
}
- void OnScanResult(LowEnergyClient* client, const ScanResult& scan_result) {
- ASSERT_TRUE(client);
- scan_result_count_++;
- last_scan_result_ = scan_result;
- }
-
private:
- int scan_result_count_;
- ScanResult last_scan_result_;
-
int connection_state_count_;
int last_mtu_;
@@ -106,6 +89,7 @@
mock_handler_.reset(new MockGattHandler());
fake_hal_gatt_iface_ = new hal::FakeBluetoothGattInterface(
nullptr,
+ nullptr,
std::static_pointer_cast<
hal::FakeBluetoothGattInterface::TestClientHandler>(mock_handler_),
nullptr);
@@ -269,98 +253,6 @@
EXPECT_EQ(uuid1, cb_uuid);
}
-TEST_F(LowEnergyClientPostRegisterTest, ScanSettings) {
- EXPECT_CALL(mock_adapter_, IsEnabled())
- .WillOnce(Return(false))
- .WillRepeatedly(Return(true));
-
- ScanSettings settings;
- std::vector<ScanFilter> filters;
-
- // Adapter is not enabled.
- EXPECT_FALSE(le_client_->StartScan(settings, filters));
-
- // TODO(jpawlowski): add tests checking settings and filter parsing when
- // implemented
-
- // These should succeed and result in a HAL call
- EXPECT_CALL(*mock_handler_, Scan(true))
- .Times(1)
- .WillOnce(Return(BT_STATUS_SUCCESS));
- EXPECT_TRUE(le_client_->StartScan(settings, filters));
-
- // These should succeed and result in a HAL call
- EXPECT_CALL(*mock_handler_, Scan(false))
- .Times(1)
- .WillOnce(Return(BT_STATUS_SUCCESS));
- EXPECT_TRUE(le_client_->StopScan());
-
- ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
-}
-
-TEST_F(LowEnergyClientPostRegisterTest, ScanRecord) {
- TestDelegate delegate;
- le_client_->SetDelegate(&delegate);
-
- EXPECT_EQ(0, delegate.scan_result_count());
-
- vector<uint8_t> kTestRecord0({ 0x02, 0x01, 0x00, 0x00 });
- vector<uint8_t> kTestRecord1({ 0x00 });
- vector<uint8_t> kTestRecord2({
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x01, 0x00
- });
- const bt_bdaddr_t kTestAddress = {
- { 0x01, 0x02, 0x03, 0x0A, 0x0B, 0x0C }
- };
- const char kTestAddressStr[] = "01:02:03:0A:0B:0C";
- const int kTestRssi = 64;
-
- // Scan wasn't started. Result should be ignored.
- fake_hal_gatt_iface_->NotifyScanResultCallback(
- kTestAddress, kTestRssi, kTestRecord0);
- EXPECT_EQ(0, delegate.scan_result_count());
-
- // Start a scan session for |le_client_|.
- EXPECT_CALL(mock_adapter_, IsEnabled())
- .Times(1)
- .WillOnce(Return(true));
- EXPECT_CALL(*mock_handler_, Scan(_))
- .Times(2)
- .WillOnce(Return(BT_STATUS_SUCCESS))
- .WillOnce(Return(BT_STATUS_SUCCESS));
- ScanSettings settings;
- std::vector<ScanFilter> filters;
- ASSERT_TRUE(le_client_->StartScan(settings, filters));
-
- fake_hal_gatt_iface_->NotifyScanResultCallback(
- kTestAddress, kTestRssi, kTestRecord0);
- EXPECT_EQ(1, delegate.scan_result_count());
- EXPECT_EQ(kTestAddressStr, delegate.last_scan_result().device_address());
- EXPECT_EQ(kTestRssi, delegate.last_scan_result().rssi());
- EXPECT_EQ(3U, delegate.last_scan_result().scan_record().size());
-
- fake_hal_gatt_iface_->NotifyScanResultCallback(
- kTestAddress, kTestRssi, kTestRecord1);
- EXPECT_EQ(2, delegate.scan_result_count());
- EXPECT_EQ(kTestAddressStr, delegate.last_scan_result().device_address());
- EXPECT_EQ(kTestRssi, delegate.last_scan_result().rssi());
- EXPECT_TRUE(delegate.last_scan_result().scan_record().empty());
-
- fake_hal_gatt_iface_->NotifyScanResultCallback(
- kTestAddress, kTestRssi, kTestRecord2);
- EXPECT_EQ(3, delegate.scan_result_count());
- EXPECT_EQ(kTestAddressStr, delegate.last_scan_result().device_address());
- EXPECT_EQ(kTestRssi, delegate.last_scan_result().rssi());
- EXPECT_EQ(62U, delegate.last_scan_result().scan_record().size());
-
- le_client_->SetDelegate(nullptr);
-}
-
MATCHER_P(BitEq, x, std::string(negation ? "isn't" : "is") +
" bitwise equal to " + ::testing::PrintToString(x)) {
static_assert(sizeof(x) == sizeof(arg), "Size mismatch");
diff --git a/service/test/low_energy_scanner_unittest.cc b/service/test/low_energy_scanner_unittest.cc
new file mode 100644
index 0000000..f966a14
--- /dev/null
+++ b/service/test/low_energy_scanner_unittest.cc
@@ -0,0 +1,346 @@
+//
+// 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.
+//
+
+#include <base/macros.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "service/adapter.h"
+#include "service/hal/fake_bluetooth_gatt_interface.h"
+#include "service/low_energy_scanner.h"
+#include "stack/include/bt_types.h"
+#include "stack/include/hcidefs.h"
+#include "test/mock_adapter.h"
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::Pointee;
+using ::testing::DoAll;
+using ::testing::Invoke;
+
+namespace bluetooth {
+namespace {
+
+class MockGattHandler
+ : public hal::FakeBluetoothGattInterface::TestScannerHandler {
+ public:
+ MockGattHandler() {
+ ON_CALL(*this, Scan(false))
+ .WillByDefault(Return(BT_STATUS_SUCCESS));
+ }
+ ~MockGattHandler() override = default;
+
+ MOCK_METHOD1(RegisterScanner, bt_status_t(bt_uuid_t*));
+ MOCK_METHOD1(UnregisterScanner, bt_status_t(int));
+ MOCK_METHOD1(Scan, bt_status_t(bool));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockGattHandler);
+};
+
+class TestDelegate : public LowEnergyScanner::Delegate {
+ public:
+ TestDelegate() : scan_result_count_(0) {
+ }
+
+ ~TestDelegate() override = default;
+
+ int scan_result_count() const { return scan_result_count_; }
+ const ScanResult& last_scan_result() const { return last_scan_result_; }
+
+ void OnScanResult(LowEnergyScanner* scanner, const ScanResult& scan_result) {
+ ASSERT_TRUE(scanner);
+ scan_result_count_++;
+ last_scan_result_ = scan_result;
+ }
+
+ private:
+ int scan_result_count_;
+ ScanResult last_scan_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestDelegate);
+};
+
+class LowEnergyScannerTest : public ::testing::Test {
+ public:
+ LowEnergyScannerTest() = default;
+ ~LowEnergyScannerTest() override = default;
+
+ void SetUp() override {
+ // Only set |mock_handler_| if a test hasn't set it.
+ if (!mock_handler_)
+ mock_handler_.reset(new MockGattHandler());
+ fake_hal_gatt_iface_ = new hal::FakeBluetoothGattInterface(
+ nullptr,
+ std::static_pointer_cast<
+ hal::FakeBluetoothGattInterface::TestScannerHandler>(mock_handler_),
+ nullptr,
+ nullptr);
+ hal::BluetoothGattInterface::InitializeForTesting(fake_hal_gatt_iface_);
+ ble_factory_.reset(new LowEnergyScannerFactory(mock_adapter_));
+ }
+
+ void TearDown() override {
+ ble_factory_.reset();
+ hal::BluetoothGattInterface::CleanUp();
+ }
+
+ protected:
+ hal::FakeBluetoothGattInterface* fake_hal_gatt_iface_;
+ testing::MockAdapter mock_adapter_;
+ std::shared_ptr<MockGattHandler> mock_handler_;
+ std::unique_ptr<LowEnergyScannerFactory> ble_factory_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LowEnergyScannerTest);
+};
+
+// Used for tests that operate on a pre-registered scanner.
+class LowEnergyScannerPostRegisterTest : public LowEnergyScannerTest {
+ public:
+ LowEnergyScannerPostRegisterTest() : next_scanner_id_(0) {
+ }
+ ~LowEnergyScannerPostRegisterTest() override = default;
+
+ void SetUp() override {
+ LowEnergyScannerTest::SetUp();
+ auto callback = [&](std::unique_ptr<LowEnergyScanner> scanner) {
+ le_scanner_ = std::move(scanner);
+ };
+ RegisterTestScanner(callback);
+ }
+
+ void TearDown() override {
+ EXPECT_CALL(*mock_handler_, UnregisterScanner(_))
+ .Times(1)
+ .WillOnce(Return(BT_STATUS_SUCCESS));
+ le_scanner_.reset();
+ LowEnergyScannerTest::TearDown();
+ }
+
+ void RegisterTestScanner(
+ const std::function<void(std::unique_ptr<LowEnergyScanner> scanner)>
+ callback) {
+ UUID uuid = UUID::GetRandom();
+ auto api_callback = [&](BLEStatus status, const UUID& in_uuid,
+ std::unique_ptr<BluetoothInstance> in_scanner) {
+ CHECK(in_uuid == uuid);
+ CHECK(in_scanner.get());
+ CHECK(status == BLE_STATUS_SUCCESS);
+
+ callback(std::unique_ptr<LowEnergyScanner>(
+ static_cast<LowEnergyScanner*>(in_scanner.release())));
+ };
+
+ EXPECT_CALL(*mock_handler_, RegisterScanner(_))
+ .Times(1)
+ .WillOnce(Return(BT_STATUS_SUCCESS));
+
+ ble_factory_->RegisterInstance(uuid, api_callback);
+
+ bt_uuid_t hal_uuid = uuid.GetBlueDroid();
+ fake_hal_gatt_iface_->NotifyRegisterScannerCallback(
+ 0, next_scanner_id_++, hal_uuid);
+ ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
+ }
+
+ protected:
+ std::unique_ptr<LowEnergyScanner> le_scanner_;
+
+ private:
+ int next_scanner_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(LowEnergyScannerPostRegisterTest);
+};
+
+TEST_F(LowEnergyScannerTest, RegisterInstance) {
+ EXPECT_CALL(*mock_handler_, RegisterScanner(_))
+ .Times(2)
+ .WillOnce(Return(BT_STATUS_FAIL))
+ .WillOnce(Return(BT_STATUS_SUCCESS));
+
+ // These will be asynchronously populated with a result when the callback
+ // executes.
+ BLEStatus status = BLE_STATUS_SUCCESS;
+ UUID cb_uuid;
+ std::unique_ptr<LowEnergyScanner> scanner;
+ int callback_count = 0;
+
+ auto callback = [&](BLEStatus in_status, const UUID& uuid,
+ std::unique_ptr<BluetoothInstance> in_scanner) {
+ status = in_status;
+ cb_uuid = uuid;
+ scanner = std::unique_ptr<LowEnergyScanner>(
+ static_cast<LowEnergyScanner*>(in_scanner.release()));
+ callback_count++;
+ };
+
+ UUID uuid0 = UUID::GetRandom();
+
+ // HAL returns failure.
+ EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
+ EXPECT_EQ(0, callback_count);
+
+ // HAL returns success.
+ EXPECT_TRUE(ble_factory_->RegisterInstance(uuid0, callback));
+ EXPECT_EQ(0, callback_count);
+
+ // Calling twice with the same UUID should fail with no additional call into
+ // the stack.
+ EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
+
+ ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
+
+ // Call with a different UUID while one is pending.
+ UUID uuid1 = UUID::GetRandom();
+ EXPECT_CALL(*mock_handler_, RegisterScanner(_))
+ .Times(1)
+ .WillOnce(Return(BT_STATUS_SUCCESS));
+ EXPECT_TRUE(ble_factory_->RegisterInstance(uuid1, callback));
+
+ // Trigger callback with an unknown UUID. This should get ignored.
+ UUID uuid2 = UUID::GetRandom();
+ bt_uuid_t hal_uuid = uuid2.GetBlueDroid();
+ fake_hal_gatt_iface_->NotifyRegisterScannerCallback(0, 0, hal_uuid);
+ EXPECT_EQ(0, callback_count);
+
+ // |uuid0| succeeds.
+ int scanner_if0 = 2; // Pick something that's not 0.
+ hal_uuid = uuid0.GetBlueDroid();
+ fake_hal_gatt_iface_->NotifyRegisterScannerCallback(
+ BT_STATUS_SUCCESS, scanner_if0, hal_uuid);
+
+ EXPECT_EQ(1, callback_count);
+ ASSERT_TRUE(scanner.get() != nullptr); // Assert to terminate in case of error
+ EXPECT_EQ(BLE_STATUS_SUCCESS, status);
+ EXPECT_EQ(scanner_if0, scanner->GetInstanceId());
+ EXPECT_EQ(uuid0, scanner->GetAppIdentifier());
+ EXPECT_EQ(uuid0, cb_uuid);
+
+ // The scanner should unregister itself when deleted.
+ EXPECT_CALL(*mock_handler_, UnregisterScanner(scanner_if0))
+ .Times(1)
+ .WillOnce(Return(BT_STATUS_SUCCESS));
+ scanner.reset();
+ ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
+
+ // |uuid1| fails.
+ int scanner_if1 = 3;
+ hal_uuid = uuid1.GetBlueDroid();
+ fake_hal_gatt_iface_->NotifyRegisterScannerCallback(
+ BT_STATUS_FAIL, scanner_if1, hal_uuid);
+
+ EXPECT_EQ(2, callback_count);
+ ASSERT_TRUE(scanner.get() == nullptr); // Assert to terminate in case of error
+ EXPECT_EQ(BLE_STATUS_FAILURE, status);
+ EXPECT_EQ(uuid1, cb_uuid);
+}
+
+TEST_F(LowEnergyScannerPostRegisterTest, ScanSettings) {
+ EXPECT_CALL(mock_adapter_, IsEnabled())
+ .WillOnce(Return(false))
+ .WillRepeatedly(Return(true));
+
+ ScanSettings settings;
+ std::vector<ScanFilter> filters;
+
+ // Adapter is not enabled.
+ EXPECT_FALSE(le_scanner_->StartScan(settings, filters));
+
+ // TODO(jpawlowski): add tests checking settings and filter parsing when
+ // implemented
+
+ // These should succeed and result in a HAL call
+ EXPECT_CALL(*mock_handler_, Scan(true))
+ .Times(1)
+ .WillOnce(Return(BT_STATUS_SUCCESS));
+ EXPECT_TRUE(le_scanner_->StartScan(settings, filters));
+
+ // These should succeed and result in a HAL call
+ EXPECT_CALL(*mock_handler_, Scan(false))
+ .Times(1)
+ .WillOnce(Return(BT_STATUS_SUCCESS));
+ EXPECT_TRUE(le_scanner_->StopScan());
+
+ ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
+}
+
+TEST_F(LowEnergyScannerPostRegisterTest, ScanRecord) {
+ TestDelegate delegate;
+ le_scanner_->SetDelegate(&delegate);
+
+ EXPECT_EQ(0, delegate.scan_result_count());
+
+ vector<uint8_t> kTestRecord0({ 0x02, 0x01, 0x00, 0x00 });
+ vector<uint8_t> kTestRecord1({ 0x00 });
+ vector<uint8_t> kTestRecord2({
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00
+ });
+ const bt_bdaddr_t kTestAddress = {
+ { 0x01, 0x02, 0x03, 0x0A, 0x0B, 0x0C }
+ };
+ const char kTestAddressStr[] = "01:02:03:0A:0B:0C";
+ const int kTestRssi = 64;
+
+ // Scan wasn't started. Result should be ignored.
+ fake_hal_gatt_iface_->NotifyScanResultCallback(
+ kTestAddress, kTestRssi, kTestRecord0);
+ EXPECT_EQ(0, delegate.scan_result_count());
+
+ // Start a scan session for |le_scanner_|.
+ EXPECT_CALL(mock_adapter_, IsEnabled())
+ .Times(1)
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mock_handler_, Scan(_))
+ .Times(2)
+ .WillOnce(Return(BT_STATUS_SUCCESS))
+ .WillOnce(Return(BT_STATUS_SUCCESS));
+ ScanSettings settings;
+ std::vector<ScanFilter> filters;
+ ASSERT_TRUE(le_scanner_->StartScan(settings, filters));
+
+ fake_hal_gatt_iface_->NotifyScanResultCallback(
+ kTestAddress, kTestRssi, kTestRecord0);
+ EXPECT_EQ(1, delegate.scan_result_count());
+ EXPECT_EQ(kTestAddressStr, delegate.last_scan_result().device_address());
+ EXPECT_EQ(kTestRssi, delegate.last_scan_result().rssi());
+ EXPECT_EQ(3U, delegate.last_scan_result().scan_record().size());
+
+ fake_hal_gatt_iface_->NotifyScanResultCallback(
+ kTestAddress, kTestRssi, kTestRecord1);
+ EXPECT_EQ(2, delegate.scan_result_count());
+ EXPECT_EQ(kTestAddressStr, delegate.last_scan_result().device_address());
+ EXPECT_EQ(kTestRssi, delegate.last_scan_result().rssi());
+ EXPECT_TRUE(delegate.last_scan_result().scan_record().empty());
+
+ fake_hal_gatt_iface_->NotifyScanResultCallback(
+ kTestAddress, kTestRssi, kTestRecord2);
+ EXPECT_EQ(3, delegate.scan_result_count());
+ EXPECT_EQ(kTestAddressStr, delegate.last_scan_result().device_address());
+ EXPECT_EQ(kTestRssi, delegate.last_scan_result().rssi());
+ EXPECT_EQ(62U, delegate.last_scan_result().scan_record().size());
+
+ le_scanner_->SetDelegate(nullptr);
+}
+
+
+} // namespace
+} // namespace bluetooth
diff --git a/service/test/mock_adapter.h b/service/test/mock_adapter.h
index f90e50f..1a762fb 100644
--- a/service/test/mock_adapter.h
+++ b/service/test/mock_adapter.h
@@ -44,6 +44,7 @@
MOCK_METHOD0(IsOffloadedScanBatchingSupported, bool());
MOCK_CONST_METHOD0(GetLowEnergyClientFactory, LowEnergyClientFactory*());
MOCK_CONST_METHOD0(GetLeAdvertiserFactory, LowEnergyAdvertiserFactory*());
+ MOCK_CONST_METHOD0(GetLeScannerFactory, LowEnergyScannerFactory*());
MOCK_CONST_METHOD0(GetGattClientFactory, GattClientFactory*());
MOCK_CONST_METHOD0(GetGattServerFactory, GattServerFactory*());
diff --git a/test/suite/gatt/gatt_test.cc b/test/suite/gatt/gatt_test.cc
index f4812ab..16f53ed 100644
--- a/test/suite/gatt/gatt_test.cc
+++ b/test/suite/gatt/gatt_test.cc
@@ -80,6 +80,10 @@
BluetoothTest::TearDown();
}
+const btgatt_scanner_interface_t* GattTest::gatt_scanner_interface() {
+ return gatt_scanner_interface_;
+}
+
const btgatt_client_interface_t* GattTest::gatt_client_interface() {
return gatt_client_interface_;
}
diff --git a/test/suite/gatt/gatt_test.h b/test/suite/gatt/gatt_test.h
index d4cc664..57e54f0 100644
--- a/test/suite/gatt/gatt_test.h
+++ b/test/suite/gatt/gatt_test.h
@@ -25,11 +25,15 @@
// helpers and callbacks for GUnit to use for testing gatt.
class GattTest : public BluetoothTest,
public bluetooth::hal::BluetoothGattInterface::ClientObserver,
+ public bluetooth::hal::BluetoothGattInterface::ScannerObserver,
public bluetooth::hal::BluetoothGattInterface::ServerObserver {
protected:
GattTest() = default;
virtual ~GattTest() = default;
+ // Gets the gatt_scanner_interface
+ const btgatt_scanner_interface_t* gatt_scanner_interface();
+
// Gets the gatt_client_interface
const btgatt_client_interface_t* gatt_client_interface();
@@ -92,6 +96,9 @@
semaphore_t* service_deleted_callback_sem_;
private:
+ // The btgatt_scanner_interface_t that all the tests use to interact with the HAL
+ const btgatt_scanner_interface_t* gatt_scanner_interface_;
+
// The gatt_client_interface that all the tests use to interact with the HAL
const btgatt_client_interface_t* gatt_client_interface_;
diff --git a/test/suite/gatt/gatt_unittest.cc b/test/suite/gatt/gatt_unittest.cc
index 9fc4f02..2f66fff 100644
--- a/test/suite/gatt/gatt_unittest.cc
+++ b/test/suite/gatt/gatt_unittest.cc
@@ -50,15 +50,6 @@
gatt_client_interface()->unregister_client(client_interface_id());
}
-TEST_F(GattTest, GattClientScanRemoteDevice) {
- // Starts BLE scan. NB: This test assumes there is a BLE beacon advertising nearby.
- gatt_client_interface()->scan(true);
- semaphore_wait(scan_result_callback_sem_);
-
- // Ends BLE scan. No callback is expected.
- gatt_client_interface()->scan(false);
-}
-
TEST_F(GattTest, GattClientAdvertise) {
// Registers a new client app.
bt_uuid_t gatt_client_uuid;