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

Commit 7de0a3f1 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Change how Advertise Data is passed to BTIF (2/3)

The way that AD data is passed right now put some additional
limitations, i.e. only one manufacturer specific data can be set, or
only one service UUID. By moving AD generation to upper layers, aother
set of limitations is removed.

Test: Covered by BleAdvertiseApiTest sl4a test
Bug: 30622771
Change-Id: Iee48ea30ec4c055eaa1ad0b1678686d261106e76
parent 66f2fc29
Loading
Loading
Loading
Loading
+7 −94
Original line number Diff line number Diff line
@@ -62,86 +62,13 @@ static inline OwnedArrayWrapper<T> OwnedArray(T* o) {
}

/* return the actual power in dBm based on the mapping in config file */
int ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
char ble_map_adv_tx_power(int tx_power_index) {
int8_t ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
int8_t ble_map_adv_tx_power(int tx_power_index) {
  if (0 <= tx_power_index && tx_power_index < BTM_BLE_ADV_TX_POWER_MAX)
    return (char)ble_tx_power[tx_power_index];
    return (int8_t)ble_tx_power[tx_power_index];
  return 0;
}

#define MIN_ADV_LENGTH 2
#define BLE_AD_DATA_LEN 31
vector<uint8_t> build_adv_data(bool set_scan_rsp, bool include_name,
                               bool incl_txpower, uint16_t appearance,
                               vector<uint8_t> manufacturer_data,
                               vector<uint8_t> service_data,
                               vector<uint8_t> service_uuid) {
  vector<uint8_t> data;

  // Flags are added by lower layers of the stack, only if needed; no need to
  // add them here.

  // TODO(jpawlowski): appearance is a dead argument, never set by upper layers.
  // Remove.

  if (include_name) {
    char* bd_name;
    BTM_ReadLocalDeviceName(&bd_name);
    size_t bd_name_len = strlen(bd_name);
    uint8_t type;

    // TODO(jpawlowski) put a better limit on device name!
    if (data.size() + MIN_ADV_LENGTH + bd_name_len > BLE_AD_DATA_LEN) {
      bd_name_len = BLE_AD_DATA_LEN - data.size() - 1;
      type = BTM_BLE_AD_TYPE_NAME_SHORT;
    } else {
      type = BTM_BLE_AD_TYPE_NAME_CMPL;
    }

    data.push_back(bd_name_len + 1);
    data.push_back(type);
    data.insert(data.end(), bd_name, bd_name + bd_name_len);
  }

  if (manufacturer_data.size()) {
    data.push_back(manufacturer_data.size() + 1);
    data.push_back(HCI_EIR_MANUFACTURER_SPECIFIC_TYPE);
    data.insert(data.end(), manufacturer_data.begin(), manufacturer_data.end());
  }

  /* TX power */
  if (incl_txpower) {
    data.push_back(MIN_ADV_LENGTH);
    data.push_back(HCI_EIR_TX_POWER_LEVEL_TYPE);
    data.push_back(0);  // lower layers will fill this value.
  }

  // TODO(jpawlowski): right now we can pass only one service, and it's size
  // determine type (16/32/128bit), this must be fixed in future!
  if (service_uuid.size()) {
    data.push_back(service_uuid.size() + 1);
    if (service_uuid.size() == LEN_UUID_16)
      data.push_back(BT_EIR_COMPLETE_16BITS_UUID_TYPE);
    else if (service_uuid.size() == LEN_UUID_32)
      data.push_back(BT_EIR_COMPLETE_32BITS_UUID_TYPE);
    else if (service_uuid.size() == LEN_UUID_128)
      data.push_back(BT_EIR_COMPLETE_128BITS_UUID_TYPE);

    data.insert(data.end(), service_uuid.begin(), service_uuid.end());
  }

  if (service_data.size()) {
    data.push_back(service_data.size() + 1);
    // TODO(jpawlowski): we can accept only 16bit uuid. Remove this restriction
    // as we move this code up the stack
    data.push_back(BT_EIR_SERVICE_DATA_16BITS_UUID_TYPE);

    data.insert(data.end(), service_data.begin(), service_data.end());
  }

  return data;
}

void bta_adv_set_data_cback(tBTA_STATUS call_status) {}

class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface {
@@ -150,6 +77,7 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface {
  void RegisterAdvertiserCb(
      base::Callback<void(uint8_t /* adv_id */, uint8_t /* status */)> cb,
      uint8_t advertiser_id, uint8_t status) {
    LOG(INFO) << __func__ << " status: " << +status << " , adveriser_id: " << +advertiser_id;
    do_in_jni_thread(Bind(cb, advertiser_id, status));
  }

@@ -170,15 +98,7 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface {
             base::Unretained(BleAdvertisingManager::Get()), advertiser_id));
  }

  void SetData(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,
               vector<uint8_t> service_data,
               vector<uint8_t> service_uuid) override {
    vector<uint8_t> data =
        build_adv_data(set_scan_rsp, include_name, include_txpower, appearance,
                       manufacturer_data, service_data, service_uuid);

  void SetData(bool set_scan_rsp, vector<uint8_t> data) override {
    uint8_t* data_ptr = nullptr;
    if (data.size()) {
      // base::Owned will free this ptr
@@ -208,6 +128,7 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface {
  }

  void MultiAdvSetParametersCb(BleAdvertiserCb cb, uint8_t status) {
    LOG(INFO) << __func__ << " status: " << +status ;
    do_in_jni_thread(Bind(cb, status));
  }

@@ -238,15 +159,7 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface {
  }

  void MultiAdvSetInstData(int advertiser_id, bool set_scan_rsp,
                           bool include_name, bool incl_txpower, int appearance,
                           vector<uint8_t> manufacturer_data,
                           vector<uint8_t> service_data,
                           vector<uint8_t> service_uuid,
                           BleAdvertiserCb cb) override {
    vector<uint8_t> data =
        build_adv_data(set_scan_rsp, include_name, incl_txpower, appearance,
                       manufacturer_data, service_data, service_uuid);

                           vector<uint8_t> data, BleAdvertiserCb cb) override {
    do_in_bta_thread(
        FROM_HERE, Bind(&BleAdvertisingManager::SetData,
                        base::Unretained(BleAdvertisingManager::Get()),
+0 −2
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ source_set("service") {
    "hal/fake_bluetooth_gatt_interface.cc",
    "hal/fake_bluetooth_interface.cc",
    "ipc/ipc_handler.cc",
    "ipc/ipc_handler_linux.cc",
    "ipc/ipc_manager.cc",
    "ipc/linux_ipc_host.cc",
    "logging_helpers.cc",
@@ -84,7 +83,6 @@ executable("service_unittests") {
  testonly = true
  sources = [
    "test/fake_hal_util.cc",
    "test/ipc_linux_unittest.cc",
    "test/settings_unittest.cc",
    "test/uuid_unittest.cc",
  ]
+15 −2
Original line number Diff line number Diff line
@@ -651,9 +651,22 @@ void HandleStartAdv(IBluetooth* bt_iface, const vector<string>& args) {
      bluetooth::AdvertiseSettings::MODE_LOW_POWER, timeout,
      bluetooth::AdvertiseSettings::TX_POWER_LEVEL_MEDIUM, connectable);

  if (include_tx_power) {
    data.push_back(0x02);
    data.push_back(bluetooth::kEIRTypeTxPower);
    data.push_back(0x00);
  }

  bluetooth::AdvertiseData adv_data(data);
  adv_data.set_include_device_name(include_name);
  adv_data.set_include_tx_power_level(include_tx_power);

  if (include_name) {
    String16 name_param;
    bt_iface->GetName(&name_param);
    std::string name(String8(name_param).string());
    data.push_back(name.length() + 1);
    data.push_back(bluetooth::kEIRTypeCompleteLocalName);
    data.insert(data.begin(), name.c_str(), name.c_str() + name.length());
  }

  bluetooth::AdvertiseData scan_rsp;

+0 −12
Original line number Diff line number Diff line
@@ -23,23 +23,11 @@ namespace bluetooth {

status_t AdvertiseData::writeToParcel(Parcel* parcel) const {
  status_t status = parcel->writeByteVector(data_);
  if (status != OK) return status;

  status = parcel->writeBool(include_device_name_);
  if (status != OK) return status;

  status = parcel->writeBool(include_tx_power_level_);
  return status;
}

status_t AdvertiseData::readFromParcel(const Parcel* parcel) {
  status_t status = parcel->readByteVector(&data_);
  if (status != OK) return status;

  status = parcel->readBool(&include_device_name_);
  if (status != OK) return status;

  status = parcel->readBool(&include_tx_power_level_);
  return status;
}

+15 −41
Original line number Diff line number Diff line
@@ -23,29 +23,17 @@

namespace bluetooth {

AdvertiseData::AdvertiseData(const std::vector<uint8_t>& data)
    : data_(data),
      include_device_name_(false),
      include_tx_power_level_(false) {
}
AdvertiseData::AdvertiseData(const std::vector<uint8_t>& data) : data_(data) {}

AdvertiseData::AdvertiseData()
    : include_device_name_(false),
      include_tx_power_level_(false) {
}
AdvertiseData::AdvertiseData() {}

AdvertiseData::AdvertiseData(const AdvertiseData& other)
    : data_(other.data_),
      include_device_name_(other.include_device_name_),
      include_tx_power_level_(other.include_tx_power_level_) {
}
AdvertiseData::AdvertiseData(const AdvertiseData& other) : data_(other.data_) {}

bool AdvertiseData::IsValid() const {
  size_t len = data_.size();

  // Consider empty data as valid.
  if (!len)
    return true;
  if (!len) return true;

  for (size_t i = 0, field_len = 0; i < len; i += (field_len + 1)) {
    field_len = data_[i];
@@ -59,8 +47,7 @@ bool AdvertiseData::IsValid() const {

    // A field length of 0 would be invalid as it should at least contain the
    // EIR field type.
    if (field_len < 1)
      return false;
    if (field_len < 1) return false;

    uint8_t type = data_[i + 1];

@@ -68,9 +55,6 @@ bool AdvertiseData::IsValid() const {
    // managed by stack.
    switch (type) {
      case HCI_EIR_FLAGS_TYPE:
    case HCI_EIR_TX_POWER_LEVEL_TYPE:
    case HCI_EIR_SHORTENED_LOCAL_NAME_TYPE:
    case HCI_EIR_COMPLETE_LOCAL_NAME_TYPE:
      case HCI_EIR_OOB_BD_ADDR_TYPE:
      case HCI_EIR_OOB_COD_TYPE:
      case HCI_EIR_OOB_SSP_HASH_C_TYPE:
@@ -86,23 +70,13 @@ bool AdvertiseData::IsValid() const {
}

bool AdvertiseData::operator==(const AdvertiseData& rhs) const {
  if (include_tx_power_level_ != rhs.include_tx_power_level_)
    return false;

  if (include_device_name_ != rhs.include_device_name_)
    return false;

  return data_ == rhs.data_;
}

AdvertiseData& AdvertiseData::operator=(const AdvertiseData& other) {
  if (this == &other)
    return *this;
  if (this == &other) return *this;

  data_ = other.data_;
  include_device_name_ = other.include_device_name_;
  include_tx_power_level_ = other.include_tx_power_level_;

  return *this;
}

Loading