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

Commit 7072fda7 authored by Rongxuan Liu's avatar Rongxuan Liu
Browse files

Divide long single gap data in le_advertising_manager

When host send long single entry gap data > 251 bytes, gd
advertising_manager would reject instead of dividing into fragments.
We need to support this usage as it's allowed by Spec. For
advertising/scan response data, we need to divide the data if length is 252 ~ 255 bytes.
For periodic advertising data, we need to divide if length is 253 ~ 255
bytes.

Change is under flag. Tested with
adb shell device_config put bluetooth com.android.bluetooth.flags.divide_long_single_gap_data true

NO_IFTTT=Modification was to fix missing libraries failure

Test: atest bluetooth_test_gd_unit
Test: manual test with long gap data and check air traces
Bug: 310217895
Bug: 303546333
Change-Id: I94bc4dbadb7a53b7008b2dca4659dbd489503318
parent ce428d6c
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -47,7 +47,8 @@ LOCAL_host_libraries := \
	$(HOST_OUT_SHARED_LIBRARIES)/libprotobuf-cpp-full.so \
	$(HOST_OUT_SHARED_LIBRARIES)/libunwindstack.so \
	$(HOST_OUT_SHARED_LIBRARIES)/libutils.so \
	$(HOST_OUT_SHARED_LIBRARIES)/liblzma.so
	$(HOST_OUT_SHARED_LIBRARIES)/liblzma.so \
	$(HOST_OUT_SHARED_LIBRARIES)/server_configurable_flags.so

LOCAL_target_executables := \
	$(TARGET_OUT_EXECUTABLES)/bluetooth_stack_with_facade
@@ -72,7 +73,8 @@ LOCAL_target_libraries := \
	$(TARGET_OUT_SHARED_LIBRARIES)/libstatslog_bt.so \
	$(TARGET_OUT_SHARED_LIBRARIES)/libunwindstack.so \
	$(TARGET_OUT_SHARED_LIBRARIES)/libutils.so \
	$(TARGET_OUT_SHARED_LIBRARIES)/libz.so
	$(TARGET_OUT_SHARED_LIBRARIES)/libz.so \
	$(TARGET_OUT_SHARED_LIBRARIES)/server_configurable_flags.so
	# libclang_rt.asan-aarch64-android.so is only generated for ASAN build and included automatically
	# on devices
	# $(TARGET_OUT_SHARED_LIBRARIES)/libclang_rt.asan-aarch64-android.so \
+4 −0
Original line number Diff line number Diff line
@@ -305,6 +305,7 @@ cc_binary {
        "libgrpc_wrap",
        "libprotobuf-cpp-full",
        "libunwindstack",
        "server_configurable_flags",
    ],
    target: {
        android: {
@@ -425,12 +426,15 @@ cc_test {
        "libbt_shim_ffi",
        "libc++fs",
        "libchrome",
        "libflagtest",
        "libflatbuffers-cpp",
        "libgmock",
        "libosi",
    ],
    shared_libs: [
        "libbase",
        "libcrypto",
        "server_configurable_flags",
    ],
    sanitize: {
        address: true,
+131 −23
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
#include "hci/le_advertising_manager.h"

#include <android_bluetooth_flags.h>

#include <iterator>
#include <memory>
#include <mutex>

@@ -32,6 +35,7 @@
#include "os/handler.h"
#include "os/log.h"
#include "os/system_properties.h"
#include "packet/fragmenting_inserter.h"

namespace bluetooth {
namespace hci {
@@ -906,10 +910,12 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb

  bool check_extended_advertising_data(std::vector<GapData> data, bool include_flag) {
    uint16_t data_len = 0;
    uint16_t data_limit = IS_FLAG_ENABLED(divide_long_single_gap_data) ? kLeMaximumGapDataLength
                                                                       : kLeMaximumFragmentLength;
    // check data size
    for (size_t i = 0; i < data.size(); i++) {
      if (data[i].size() > kLeMaximumFragmentLength) {
        LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength);
      if (data[i].size() > data_limit) {
        LOG_WARN("AD data len shall not greater than %d", data_limit);
        return false;
      }
      data_len += data[i].size();
@@ -993,10 +999,13 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
      } break;
      case (AdvertisingApiType::EXTENDED): {
        uint16_t data_len = 0;
        bool divide_gap_flag = IS_FLAG_ENABLED(divide_long_single_gap_data);
        // check data size
        for (size_t i = 0; i < data.size(); i++) {
          if (data[i].size() > kLeMaximumFragmentLength) {
            LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength);
          uint16_t data_limit =
              divide_gap_flag ? kLeMaximumGapDataLength : kLeMaximumFragmentLength;
          if (data[i].size() > data_limit) {
            LOG_WARN("AD data len shall not greater than %d", data_limit);
            if (advertising_callbacks_ != nullptr) {
              if (set_scan_rsp) {
                advertising_callbacks_->OnScanResponseDataSet(
@@ -1034,6 +1043,24 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
          uint16_t sub_data_len = 0;
          Operation operation = Operation::FIRST_FRAGMENT;

          if (divide_gap_flag) {
            std::vector<std::unique_ptr<packet::RawBuilder>> fragments;
            packet::FragmentingInserter it(
                kLeMaximumFragmentLength, std::back_insert_iterator(fragments));
            for (auto gap_data : data) {
              gap_data.Serialize(it);
            }
            it.finalize();

            for (size_t i = 0; i < fragments.size(); i++) {
              send_data_fragment_with_raw_builder(
                  advertiser_id,
                  set_scan_rsp,
                  std::move(fragments[i]),
                  (i == fragments.size() - 1) ? Operation::LAST_FRAGMENT : operation);
              operation = Operation::INTERMEDIATE_FRAGMENT;
            }
          } else {
            for (size_t i = 0; i < data.size(); i++) {
              if (sub_data_len + data[i].size() > kLeMaximumFragmentLength) {
                send_data_fragment(advertiser_id, set_scan_rsp, sub_data, operation);
@@ -1046,6 +1073,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
            }
            send_data_fragment(advertiser_id, set_scan_rsp, sub_data, Operation::LAST_FRAGMENT);
          }
        }
      } break;
    }
  }
@@ -1080,6 +1108,45 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
    }
  }

  void send_data_fragment_with_raw_builder(
      AdvertiserId advertiser_id,
      bool set_scan_rsp,
      std::unique_ptr<packet::RawBuilder> data,
      Operation operation) {
    if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) {
      if (set_scan_rsp) {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedScanResponseDataRawBuilder::Create(
                advertiser_id, operation, kFragment_preference, std::move(data)),
            module_handler_->BindOnceOn(
                this,
                &impl::check_status_with_id<LeSetExtendedScanResponseDataCompleteView>,
                advertiser_id));
      } else {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedAdvertisingDataRawBuilder::Create(
                advertiser_id, operation, kFragment_preference, std::move(data)),
            module_handler_->BindOnceOn(
                this,
                &impl::check_status_with_id<LeSetExtendedAdvertisingDataCompleteView>,
                advertiser_id));
      }
    } else {
      // For first and intermediate fragment, do not trigger advertising_callbacks_.
      if (set_scan_rsp) {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedScanResponseDataRawBuilder::Create(
                advertiser_id, operation, kFragment_preference, std::move(data)),
            module_handler_->BindOnce(check_complete<LeSetExtendedScanResponseDataCompleteView>));
      } else {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedAdvertisingDataRawBuilder::Create(
                advertiser_id, operation, kFragment_preference, std::move(data)),
            module_handler_->BindOnce(check_complete<LeSetExtendedAdvertisingDataCompleteView>));
      }
    }
  }

  void enable_advertiser(
      AdvertiserId advertiser_id, bool enable, uint16_t duration, uint8_t max_extended_advertising_events) {
    EnabledSet curr_set;
@@ -1160,10 +1227,12 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb

  void set_periodic_data(AdvertiserId advertiser_id, std::vector<GapData> data) {
    uint16_t data_len = 0;
    bool divide_gap_flag = IS_FLAG_ENABLED(divide_long_single_gap_data);
    // check data size
    for (size_t i = 0; i < data.size(); i++) {
      if (data[i].size() > kLeMaximumFragmentLength) {
        LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength);
      uint16_t data_limit = divide_gap_flag ? kLeMaximumGapDataLength : kLeMaximumFragmentLength;
      if (data[i].size() > data_limit) {
        LOG_WARN("AD data len shall not greater than %d", data_limit);
        if (advertising_callbacks_ != nullptr) {
          advertising_callbacks_->OnPeriodicAdvertisingDataSet(
              advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
@@ -1183,13 +1252,32 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
      return;
    }

    if (data_len <= kLeMaximumFragmentLength) {
    uint16_t data_fragment_limit =
        divide_gap_flag ? kLeMaximumPeriodicDataFragmentLength : kLeMaximumFragmentLength;
    if (data_len <= data_fragment_limit) {
      send_periodic_data_fragment(advertiser_id, data, Operation::COMPLETE_ADVERTISEMENT);
    } else {
      std::vector<GapData> sub_data;
      uint16_t sub_data_len = 0;
      Operation operation = Operation::FIRST_FRAGMENT;

      if (divide_gap_flag) {
        std::vector<std::unique_ptr<packet::RawBuilder>> fragments;
        packet::FragmentingInserter it(
            kLeMaximumPeriodicDataFragmentLength, std::back_insert_iterator(fragments));
        for (auto gap_data : data) {
          gap_data.Serialize(it);
        }
        it.finalize();

        for (size_t i = 0; i < fragments.size(); i++) {
          send_periodic_data_fragment_with_raw_builder(
              advertiser_id,
              std::move(fragments[i]),
              (i == fragments.size() - 1) ? Operation::LAST_FRAGMENT : operation);
          operation = Operation::INTERMEDIATE_FRAGMENT;
        }
      } else {
        for (size_t i = 0; i < data.size(); i++) {
          if (sub_data_len + data[i].size() > kLeMaximumFragmentLength) {
            send_periodic_data_fragment(advertiser_id, sub_data, operation);
@@ -1203,6 +1291,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
        send_periodic_data_fragment(advertiser_id, sub_data, Operation::LAST_FRAGMENT);
      }
    }
  }

  void send_periodic_data_fragment(AdvertiserId advertiser_id, std::vector<GapData> data, Operation operation) {
    if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) {
@@ -1218,6 +1307,25 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
    }
  }

  void send_periodic_data_fragment_with_raw_builder(
      AdvertiserId advertiser_id, std::unique_ptr<packet::RawBuilder> data, Operation operation) {
    if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) {
      le_advertising_interface_->EnqueueCommand(
          hci::LeSetPeriodicAdvertisingDataRawBuilder::Create(
              advertiser_id, operation, std::move(data)),
          module_handler_->BindOnceOn(
              this,
              &impl::check_status_with_id<LeSetPeriodicAdvertisingDataCompleteView>,
              advertiser_id));
    } else {
      // For first and intermediate fragment, do not trigger advertising_callbacks_.
      le_advertising_interface_->EnqueueCommand(
          hci::LeSetPeriodicAdvertisingDataRawBuilder::Create(
              advertiser_id, operation, std::move(data)),
          module_handler_->BindOnce(check_complete<LeSetPeriodicAdvertisingDataCompleteView>));
    }
  }

  void enable_periodic_advertising(AdvertiserId advertiser_id, bool enable, bool include_adi) {
    if (!controller_->SupportsBlePeriodicAdvertising()) {
      return;
+2 −0
Original line number Diff line number Diff line
@@ -104,6 +104,8 @@ class LeAdvertisingManager : public bluetooth::Module {
  static constexpr uint8_t kInvalidHandle = 0xFF;
  static constexpr uint8_t kAdvertisingSetIdMask = 0x0F;
  static constexpr uint16_t kLeMaximumFragmentLength = 251;
  static constexpr uint16_t kLeMaximumPeriodicDataFragmentLength = 252;
  static constexpr uint16_t kLeMaximumGapDataLength = 255;
  static constexpr FragmentPreference kFragment_preference = FragmentPreference::CONTROLLER_SHOULD_NOT;
  LeAdvertisingManager();
  LeAdvertisingManager(const LeAdvertisingManager&) = delete;
+395 −34

File changed.

Preview size limit exceeded, changes collapsed.

Loading