Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fa8c1c4 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Andre Eisenbach
Browse files

Make Bluetooth LE multi-advertising testable

This patch turns the code that manages LE multi-advertising into the
BleAdvertisingManager class. All HCI calls made by this code were
abstracted into BleAdvertiserHciInterface.

Thanks to those changes, we can mock BleAdvertiserHciInterface and test
the advertising manager.

The BleAdvertisingManagerTest, still has some dependencies on other
code from the "stack" module. These have to be implemented on top of the
test file. In the future, this dependencies should be replaced by mockable
classes.

Test: Tests covering the change are added in this patch.
Bug: 30622771
Change-Id: I4a363678815c235ee01255f462db2a671ef89610
parent 09d3f800
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ static_library("btif") {

    #TODO(jpawlowski): heavily depends on Android,
    #   "src/btif_avrcp_audio_track.cc",
    "src/btif_ble_advertiser.cc",
    "src/btif_config.cc",
    "src/btif_config_transcode.cc",
    "src/btif_core.cc",
+105 −100
Original line number Diff line number Diff line
@@ -23,8 +23,8 @@

#include <base/bind.h>

#include "bta_closure_api.h"
#include "ble_advertiser.h"
#include "bta_closure_api.h"
#include "bta_gatt_api.h"
#include "btif_common.h"
#include "btif_gatt.h"
@@ -49,62 +49,12 @@ extern const btgatt_callbacks_t *bt_gatt_callbacks;

namespace {

bt_status_t btif_multiadv_enable(int advertiser_id, bool enable,
                                        int timeout_s);
bt_status_t btif_multiadv_enable(int advertiser_id, bool enable, int timeout_s);
void btif_multi_adv_stop_cb(void *data) {
  int advertiser_id = PTR_TO_INT(data);
  btif_multiadv_enable(advertiser_id, false, 0);  // Does context switch
}

void multi_adv_enable_cb_impl(int advertiser_id, int status, bool enable) {
  HAL_CBACK(bt_gatt_callbacks, advertiser->multi_adv_enable_cb, advertiser_id,
            status, enable);
  if (enable == false) {
      btif_multi_adv_timer_ctrl(
          advertiser_id, (status == BTA_GATT_OK) ? btif_multi_adv_stop_cb : NULL);
  }
}

void multi_adv_set_params_cb_impl(int advertiser_id, int status) {
  HAL_CBACK(bt_gatt_callbacks, advertiser->multi_adv_set_params_cb, advertiser_id,
            status);
  btif_multi_adv_timer_ctrl(
      advertiser_id, (status == BTA_GATT_OK) ? btif_multi_adv_stop_cb : NULL);
}

void multi_adv_data_cb_impl(int advertiser_id, int status) {
  btif_gattc_clear_clientif(advertiser_id, false);
  HAL_CBACK(bt_gatt_callbacks, advertiser->multi_adv_data_cb, advertiser_id,
            status);
}

bt_uuid_t registering_uuid;

void multi_adv_reg_cb_impl(int advertiser_id, int status) {
  HAL_CBACK(bt_gatt_callbacks, advertiser->register_advertiser_cb, status,
            advertiser_id, &registering_uuid);
}

void bta_gattc_multi_adv_cback(tBTM_BLE_MULTI_ADV_EVT event, uint8_t advertiser_id,
                               tBTA_STATUS status) {

  BTIF_TRACE_DEBUG("%s: advertiser_id: %d, Status:%x", __func__, advertiser_id, status);

  if (event == BTM_BLE_MULTI_ADV_REG_EVT)
    do_in_jni_thread(Bind(multi_adv_reg_cb_impl, advertiser_id, status));
  else if (event == BTM_BLE_MULTI_ADV_PARAM_EVT)
    do_in_jni_thread(Bind(multi_adv_set_params_cb_impl, advertiser_id, status));
  else if (event == BTM_BLE_MULTI_ADV_ENB_EVT)
    do_in_jni_thread(
        Bind(multi_adv_enable_cb_impl, advertiser_id, status, true));
  else if (event == BTM_BLE_MULTI_ADV_DISABLE_EVT)
    do_in_jni_thread(
        Bind(multi_adv_enable_cb_impl, advertiser_id, status, false));
  else if (event == BTM_BLE_MULTI_ADV_DATA_EVT)
    do_in_jni_thread(
        Bind(multi_adv_data_cb_impl, advertiser_id, status));
}

void bta_adv_set_data_cback(tBTA_STATUS call_status) {
  do_in_jni_thread(Bind(&btif_gattc_cleanup_inst_cb, STD_ADV_INSTID, false));
}
@@ -120,17 +70,15 @@ void btif_adv_set_data_impl(btif_adv_data_t *p_adv_data) {
           sizeof(tBTM_BLE_ADV_DATA));

    if (!p_adv_data->set_scan_rsp) {
      do_in_bta_thread(FROM_HERE,
          base::Bind(&BTM_BleWriteAdvData,
      do_in_bta_thread(
          FROM_HERE, base::Bind(&BTM_BleWriteAdvData,
                                p_multi_adv_data_cb->inst_cb[cbindex].mask,
                     base::Owned(adv_cfg),
                     bta_adv_set_data_cback));
                                base::Owned(adv_cfg), bta_adv_set_data_cback));
    } else {
      do_in_bta_thread(FROM_HERE,
          base::Bind(&BTM_BleWriteScanRsp,
      do_in_bta_thread(
          FROM_HERE, base::Bind(&BTM_BleWriteScanRsp,
                                p_multi_adv_data_cb->inst_cb[cbindex].mask,
                     base::Owned(adv_cfg),
                     bta_adv_set_data_cback));
                                base::Owned(adv_cfg), bta_adv_set_data_cback));
    }
  } else {
    BTIF_TRACE_ERROR("%s: failed to get instance data cbindex: %d", __func__,
@@ -141,8 +89,7 @@ void btif_adv_set_data_impl(btif_adv_data_t *p_adv_data) {
bt_status_t btif_adv_set_data(int advertiser_id, bool set_scan_rsp,
                              bool include_name, bool include_txpower,
                              int min_interval, int max_interval,
                              int appearance,
                              vector<uint8_t> manufacturer_data,
                              int appearance, vector<uint8_t> manufacturer_data,
                              vector<uint8_t> service_data,
                              vector<uint8_t> service_uuid) {
  CHECK_BTGATT_INIT();
@@ -154,13 +101,23 @@ bt_status_t btif_adv_set_data(int advertiser_id, bool set_scan_rsp,
      max_interval, appearance, std::move(manufacturer_data),
      std::move(service_data), std::move(service_uuid), adv_data);

  return do_in_jni_thread(
      Bind(&btif_adv_set_data_impl, base::Owned(adv_data)));
  return do_in_jni_thread(Bind(&btif_adv_set_data_impl, base::Owned(adv_data)));
}

void multi_adv_set_params_cb_impl(int advertiser_id, int status) {
  HAL_CBACK(bt_gatt_callbacks, advertiser->multi_adv_set_params_cb,
            advertiser_id, status);
  btif_multi_adv_timer_ctrl(
      advertiser_id, (status == BTA_GATT_OK) ? btif_multi_adv_stop_cb : NULL);
}

void multi_adv_set_params_cb(uint8_t advertiser_id, uint8_t status) {
  do_in_jni_thread(Bind(multi_adv_set_params_cb_impl, advertiser_id, status));
}

void btif_multiadv_set_params_impl(int advertiser_id, int min_interval,
                                          int max_interval, int adv_type,
                                          int chnl_map, int tx_power) {
                                   int max_interval, int adv_type, int chnl_map,
                                   int tx_power) {
  tBTM_BLE_ADV_PARAMS param;
  param.adv_int_min = min_interval;
  param.adv_int_max = max_interval;
@@ -175,9 +132,14 @@ void btif_multiadv_set_params_impl(int advertiser_id, int min_interval,
         sizeof(tBTM_BLE_ADV_PARAMS));

  tBTM_BLE_ADV_PARAMS *params = new tBTM_BLE_ADV_PARAMS;
  memcpy(params, &(p_multi_adv_data_cb->inst_cb[advertiser_id].param), sizeof(tBTM_BLE_ADV_PARAMS));
  do_in_bta_thread(FROM_HERE,
      base::Bind(&BTM_BleAdvSetParameters, advertiser_id, base::Owned(params)));
  memcpy(params, &(p_multi_adv_data_cb->inst_cb[advertiser_id].param),
         sizeof(tBTM_BLE_ADV_PARAMS));
  do_in_bta_thread(
      FROM_HERE,
      base::Bind(&BleAdvertisingManager::SetParameters,
                 base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
                 base::Owned(params),
                 base::Bind(multi_adv_set_params_cb, advertiser_id)));
}

bt_status_t btif_multiadv_set_params(int advertiser_id, int min_interval,
@@ -189,6 +151,16 @@ bt_status_t btif_multiadv_set_params(int advertiser_id, int min_interval,
                               tx_power));
}

void multi_adv_data_cb_impl(int advertiser_id, int status) {
  btif_gattc_clear_clientif(advertiser_id, false);
  HAL_CBACK(bt_gatt_callbacks, advertiser->multi_adv_data_cb, advertiser_id,
            status);
}

void multi_adv_data_cb(uint8_t advertiser_id, uint8_t status) {
  do_in_jni_thread(Bind(multi_adv_data_cb_impl, advertiser_id, status));
}

void btif_multiadv_set_data_impl(btif_adv_data_t *p_adv_data) {
  uint8_t advertiser_id = p_adv_data->advertiser_id;
  if (!btif_gattc_copy_datacb(advertiser_id, p_adv_data, true)) {
@@ -201,9 +173,14 @@ void btif_multiadv_set_data_impl(btif_adv_data_t *p_adv_data) {
      btif_obtain_multi_adv_data_cb();

  do_in_bta_thread(FROM_HERE,
    base::Bind(&BTM_BleAdvSetData, advertiser_id, p_adv_data->set_scan_rsp,
                   base::Bind(&BleAdvertisingManager::SetData,
                              base::Unretained(BleAdvertisingManager::Get()),
                              advertiser_id, p_adv_data->set_scan_rsp,
                              p_multi_adv_data_cb->inst_cb[advertiser_id].mask,
              (tBTM_BLE_ADV_DATA*)&p_multi_adv_data_cb->inst_cb[advertiser_id].data));
                              (tBTM_BLE_ADV_DATA *)&p_multi_adv_data_cb
                                  ->inst_cb[advertiser_id]
                                  .data,
                              base::Bind(multi_adv_data_cb, advertiser_id)));
}

bt_status_t btif_multiadv_set_data(int advertiser_id, bool set_scan_rsp,
@@ -224,38 +201,64 @@ bt_status_t btif_multiadv_set_data(int advertiser_id, bool set_scan_rsp,
      max_interval, appearance, std::move(manufacturer_data),
      std::move(service_data), std::move(service_uuid), multi_adv_data_inst);

  return do_in_jni_thread(Bind(&btif_multiadv_set_data_impl,
                               base::Owned(multi_adv_data_inst)));
  return do_in_jni_thread(
      Bind(&btif_multiadv_set_data_impl, base::Owned(multi_adv_data_inst)));
}

void btif_multiadv_enable_impl(int advertiser_id, bool enable,
                                      int timeout_s) {
  BTIF_TRACE_DEBUG("%s: advertiser_id: %d, enable: %d", __func__,
                   advertiser_id, enable);
void multi_adv_enable_cb_impl(int advertiser_id, int status, bool enable) {
  HAL_CBACK(bt_gatt_callbacks, advertiser->multi_adv_enable_cb, advertiser_id,
            status, enable);
  if (!enable) {
    btif_multi_adv_timer_ctrl(
        advertiser_id, (status == BTA_GATT_OK) ? btif_multi_adv_stop_cb : NULL);
  }
}

void multi_adv_enable_cb(bool enable, uint8_t advertiser_id,
                      uint8_t status) {
    do_in_jni_thread(
        Bind(multi_adv_enable_cb_impl, advertiser_id, status, enable));
}

void btif_multiadv_enable_impl(int advertiser_id, bool enable, int timeout_s) {
  BTIF_TRACE_DEBUG("%s: advertiser_id: %d, enable: %d", __func__, advertiser_id,
                   enable);

  btgatt_multi_adv_common_data *p_multi_adv_data_cb =
      btif_obtain_multi_adv_data_cb();
  if (enable)
    p_multi_adv_data_cb->inst_cb[advertiser_id].timeout_s = timeout_s;

  do_in_bta_thread(FROM_HERE,
      base::Bind(&BTM_BleAdvEnable, advertiser_id, enable));
  if (enable) p_multi_adv_data_cb->inst_cb[advertiser_id].timeout_s = timeout_s;

  do_in_bta_thread(
      FROM_HERE,
      base::Bind(&BleAdvertisingManager::Enable,
                 base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
                 enable,
                 base::Bind(multi_adv_enable_cb, enable, advertiser_id)));
}

bt_status_t btif_multiadv_enable(int advertiser_id, bool enable,
                                 int timeout_s) {
  CHECK_BTGATT_INIT();
  return do_in_jni_thread(Bind(btif_multiadv_enable_impl, advertiser_id,
                               enable, timeout_s));
  return do_in_jni_thread(
      Bind(btif_multiadv_enable_impl, advertiser_id, enable, timeout_s));
}

void multi_adv_reg_cb_impl(bt_uuid_t uuid, int advertiser_id, int status) {
  HAL_CBACK(bt_gatt_callbacks, advertiser->register_advertiser_cb, status,
            advertiser_id, &uuid);
}

void multi_adv_reg_cb(bt_uuid_t uuid, uint8_t advertiser_id, uint8_t status) {
  do_in_jni_thread(Bind(multi_adv_reg_cb_impl, uuid, advertiser_id, status));
}

bt_status_t btif_multiadv_register(bt_uuid_t *uuid) {
  btif_gattc_incr_app_count();

  registering_uuid = *uuid;

  do_in_bta_thread(FROM_HERE,
        base::Bind(&BTM_BleAdvRegister, bta_gattc_multi_adv_cback));
                   base::Bind(&BleAdvertisingManager::RegisterAdvertiser,
                              base::Unretained(BleAdvertisingManager::Get()),
                              base::Bind(multi_adv_reg_cb, *uuid)));
  return (bt_status_t)BTA_GATT_OK;
}

@@ -264,7 +267,9 @@ bt_status_t btif_multiadv_unregister(int advertiser_id) {
  btif_gattc_decr_app_count();

  do_in_bta_thread(FROM_HERE,
        base::Bind(&BTM_BleAdvUnregister, advertiser_id));
                   base::Bind(&BleAdvertisingManager::Unregister,
                              base::Unretained(BleAdvertisingManager::Get()),
                              advertiser_id));

  return (bt_status_t)BTA_GATT_OK;
}
+6 −0
Original line number Diff line number Diff line
@@ -584,6 +584,12 @@ bt_status_t btif_disable_bluetooth(void)
{
    BTIF_TRACE_DEBUG("BTIF DISABLE BLUETOOTH");

#if (BLE_INCLUDED == TRUE)
    btm_ble_multi_adv_cleanup();
    // TODO(jpawlowski): this should do whole BTA_VendorCleanup(), but it would kill
    // the stack now.
#endif

    btif_dm_on_disable();
    /* cleanup rfcomm & l2cap api */
    btif_sock_cleanup();
+33 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ LOCAL_SRC_FILES := \
    ./bnep/bnep_api.c \
    ./hcic/hciblecmds.c \
    ./hcic/hcicmds.c \
    ./btm/ble_advertiser_hci_interface.cc \
    ./btm/btm_ble.c \
    ./btm/btm_sec.c \
    ./btm/btm_inq.c \
@@ -185,3 +186,35 @@ LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)

include $(BUILD_NATIVE_TEST)


# Bluetooth stack multi-advertising unit tests for target
# ========================================================
include $(CLEAR_VARS)

LOCAL_CPP_EXTENSION := .cc

LOCAL_C_INCLUDES := \
                   $(LOCAL_PATH)/include \
                   $(LOCAL_PATH)/../include \
                   $(LOCAL_PATH)/../ \
                   $(LOCAL_PATH)/btm \
                   $(LOCAL_PATH)/../btcore/include \
                   $(LOCAL_PATH)/../hci/include \
                   $(LOCAL_PATH)/../include \
                   $(LOCAL_PATH)/../utils/include \
                   $(LOCAL_PATH)/../ \
                   $(bluetooth_C_INCLUDES)

LOCAL_SRC_FILES := btm/btm_ble_multi_adv.cc \
                   test/ble_advertiser_test.cc
LOCAL_SHARED_LIBRARIES := libcutils libchrome
LOCAL_STATIC_LIBRARIES := liblog libgmock libgtest
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE := net_test_stack_multi_adv

LOCAL_CFLAGS += $(bluetooth_CFLAGS)
LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
LOCAL_CPPFLAGS += $(bluetooth_CPPFLAGS)

include $(BUILD_NATIVE_TEST)
+39 −1
Original line number Diff line number Diff line
@@ -151,7 +151,6 @@ static_library("stack") {
    "sdp",
    "smp",
    "srvc",
    "//osi/include",
    "//btcore/include",
    "//vnd/include",
    "//vnd/ble",
@@ -172,3 +171,42 @@ static_library("stack") {
    "//third_party/libchrome:base"
  ]
}

executable("stack_unittests") {
  testonly = true
  sources = [
    "test/ble_advertiser_test.cc",
    "test/stack_a2d_test.cc",
  ]

  include_dirs = [
    "include",
    "//",
    "//audio_a2dp_hw",
    "//bta/include",
    "//bta/sys",
    "//btcore/include",
    "//embdrv/sbc/encoder/include",
    "//hci/include",
    "//include",
    "//stack/a2dp",
    "//stack/btm",
    "//stack/include",
    "//third_party/tinyxml2",
    "//udrv/include",
    "//utils/include",
    "//vnd/include"
  ]

  deps = [
    ":stack",
    "//osi",
    "//btcore",
    "//device",
    "//hci",
    "//main:bluetooth.default",
    "//third_party/googletest:gmock_main",
    "//third_party/libchrome:base",
  ]
}
Loading