/*
 * Copyright 2019 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 "hci/le_advertising_manager.h"

#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>

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

#include "common/init_flags.h"
#include "common/strings.h"
#include "hardware/ble_advertiser.h"
#include "hci/acl_manager.h"
#include "hci/controller.h"
#include "hci/event_checkers.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "hci/le_advertising_interface.h"
#include "hci/vendor_specific_event_manager.h"
#include "module.h"
#include "os/handler.h"
#include "os/log.h"
#include "os/system_properties.h"
#include "packet/fragmenting_inserter.h"

namespace bluetooth {
namespace hci {

const ModuleFactory LeAdvertisingManager::Factory = ModuleFactory([]() { return new LeAdvertisingManager(); });
constexpr int kIdLocal = 0xff;  // Id for advertiser not register from Java layer
constexpr uint16_t kLenOfFlags = 0x03;
constexpr int64_t kLeAdvertisingTxPowerMin = -127;
constexpr int64_t kLeAdvertisingTxPowerMax = 20;
constexpr int64_t kLeTxPathLossCompMin = -128;
constexpr int64_t kLeTxPathLossCompMax = 127;

// system properties
const std::string kLeTxPathLossCompProperty = "bluetooth.hardware.radio.le_tx_path_loss_comp_db";

enum class AdvertisingApiType {
  LEGACY = 1,
  ANDROID_HCI = 2,
  EXTENDED = 3,
};

enum class AdvertisingFlag : uint8_t {
  LE_LIMITED_DISCOVERABLE = 0x01,
  LE_GENERAL_DISCOVERABLE = 0x02,
  BR_EDR_NOT_SUPPORTED = 0x04,
  SIMULTANEOUS_LE_AND_BR_EDR_CONTROLLER = 0x08,
  SIMULTANEOUS_LE_AND_BR_EDR_HOST = 0x10,
};

struct Advertiser {
  os::Handler* handler;
  AddressWithType current_address;
  // note: may not be the same as the requested_address_type, depending on the address policy
  AdvertiserAddressType address_type;
  base::OnceCallback<void(uint8_t /* status */)> status_callback;
  base::OnceCallback<void(uint8_t /* status */)> timeout_callback;
  common::Callback<void(Address, AddressType)> scan_callback;
  common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback;
  int8_t tx_power;
  uint16_t duration;
  uint8_t max_extended_advertising_events;
  bool started = false;
  bool is_legacy = false;
  bool connectable = false;
  bool discoverable = false;
  bool directed = false;
  bool in_use = false;
  std::unique_ptr<os::Alarm> address_rotation_alarm;
};

/**
 * Determines the address type to use, based on the requested type and the address manager policy,
 * by selecting the "strictest" of the two. Strictness is defined in ascending order as
 * RPA -> NRPA -> Public. Thus:
 * (1) if the host only supports the public/static address policy, all advertisements will be public
 * (2) if the host supports only non-resolvable addresses, then advertisements will never use RPA
 * (3) if the host supports RPAs, then the requested type will always be honored
 */
AdvertiserAddressType GetAdvertiserAddressTypeFromRequestedTypeAndPolicy(
    AdvertiserAddressType requested_address_type, LeAddressManager::AddressPolicy address_policy) {
  switch (address_policy) {
    case LeAddressManager::AddressPolicy::USE_PUBLIC_ADDRESS:
    case LeAddressManager::AddressPolicy::USE_STATIC_ADDRESS:
      return AdvertiserAddressType::PUBLIC;
    case LeAddressManager::AddressPolicy::USE_RESOLVABLE_ADDRESS:
      return requested_address_type;
    case LeAddressManager::AddressPolicy::USE_NON_RESOLVABLE_ADDRESS:
      return requested_address_type == AdvertiserAddressType::RESOLVABLE_RANDOM
                 ? AdvertiserAddressType::NONRESOLVABLE_RANDOM
                 : requested_address_type;
    default:
      log::fatal("unreachable");
      return AdvertiserAddressType::PUBLIC;
  }
}

/**
 * Determines the address type to use for non-connectable advertisement.
 * (1) if the host only supports public/static address policy, non-connectable advertisement
 *     can use both Public and NRPA if requested. Use NRPA if RPA is requested.
 * (2) in other cases, based on the requested type and the address manager policy.
 */
AdvertiserAddressType GetAdvertiserAddressTypeNonConnectable(
    AdvertiserAddressType requested_address_type, LeAddressManager::AddressPolicy address_policy) {
  switch (address_policy) {
    case LeAddressManager::AddressPolicy::USE_PUBLIC_ADDRESS:
    case LeAddressManager::AddressPolicy::USE_STATIC_ADDRESS:
      return requested_address_type == AdvertiserAddressType::RESOLVABLE_RANDOM
                 ? AdvertiserAddressType::NONRESOLVABLE_RANDOM
                 : requested_address_type;
    default:
      return GetAdvertiserAddressTypeFromRequestedTypeAndPolicy(
          requested_address_type, address_policy);
  }
}

struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallback {
  impl(Module* module) : module_(module), le_advertising_interface_(nullptr), num_instances_(0) {}

  ~impl() {
    if (address_manager_registered) {
      le_address_manager_->Unregister(this);
    }
    advertising_sets_.clear();
  }

  void start(
      os::Handler* handler,
      hci::HciLayer* hci_layer,
      hci::Controller* controller,
      hci::AclManager* acl_manager,
      hci::VendorSpecificEventManager* vendor_specific_event_manager) {
    module_handler_ = handler;
    hci_layer_ = hci_layer;
    controller_ = controller;
    le_maximum_advertising_data_length_ = controller_->GetLeMaximumAdvertisingDataLength();
    acl_manager_ = acl_manager;
    le_address_manager_ = acl_manager->GetLeAddressManager();
    num_instances_ = controller_->GetLeNumberOfSupportedAdverisingSets();

    le_advertising_interface_ =
        hci_layer_->GetLeAdvertisingInterface(module_handler_->BindOn(this, &LeAdvertisingManager::impl::handle_event));
    vendor_specific_event_manager->RegisterEventHandler(
        hci::VseSubeventCode::BLE_STCHANGE,
        handler->BindOn(this, &LeAdvertisingManager::impl::multi_advertising_state_change));

    if (controller_->SupportsBleExtendedAdvertising()) {
      advertising_api_type_ = AdvertisingApiType::EXTENDED;
    } else if (controller_->IsSupported(hci::OpCode::LE_MULTI_ADVT)) {
      advertising_api_type_ = AdvertisingApiType::ANDROID_HCI;
      num_instances_ = controller_->GetVendorCapabilities().max_advt_instances_;
      // number of LE_MULTI_ADVT start from 1
      num_instances_ += 1;
    } else {
      advertising_api_type_ = AdvertisingApiType::LEGACY;
      int vendor_version = os::GetAndroidVendorReleaseVersion();
      if (vendor_version != 0 && vendor_version <= 11 && os::IsRootCanalEnabled()) {
        log::info(
            "LeReadAdvertisingPhysicalChannelTxPower is not supported on Android R RootCanal, "
            "default to 0");
        le_physical_channel_tx_power_ = 0;
      } else {
        hci_layer_->EnqueueCommand(
            LeReadAdvertisingPhysicalChannelTxPowerBuilder::Create(),
            handler->BindOnceOn(this, &impl::on_read_advertising_physical_channel_tx_power));
      }
    }
    enabled_sets_ = std::vector<EnabledSet>(num_instances_);
    for (size_t i = 0; i < enabled_sets_.size(); i++) {
      enabled_sets_[i].advertising_handle_ = kInvalidHandle;
    }
    le_tx_path_loss_comp_ = get_tx_path_loss_compensation();
  }

  int8_t get_tx_path_loss_compensation() {
    int8_t compensation = 0;
    auto compensation_prop = os::GetSystemProperty(kLeTxPathLossCompProperty);
    if (compensation_prop) {
      auto compensation_number = common::Int64FromString(compensation_prop.value());
      if (compensation_number) {
        int64_t number = compensation_number.value();
        if (number < kLeTxPathLossCompMin || number > kLeTxPathLossCompMax) {
          log::error("Invalid number for tx path loss compensation: {}", number);
        } else {
          compensation = number;
        }
      }
    }
    log::info("Tx path loss compensation: {}", compensation);
    return compensation;
  }

  int8_t get_tx_power_after_calibration(int8_t tx_power) {
    if (le_tx_path_loss_comp_ == 0) {
      return tx_power;
    }
    int8_t calibrated_tx_power = tx_power;
    int64_t number = tx_power + le_tx_path_loss_comp_;
    if (number < kLeAdvertisingTxPowerMin || number > kLeAdvertisingTxPowerMax) {
      log::error("Invalid number for calibrated tx power: {}", number);
    } else {
      calibrated_tx_power = number;
    }
    log::info("tx_power: {}, calibrated_tx_power: {}", tx_power, calibrated_tx_power);
    return calibrated_tx_power;
  }

  size_t GetNumberOfAdvertisingInstances() const {
    return num_instances_;
  }

  size_t GetNumberOfAdvertisingInstancesInUse() const {
    return std::count_if(advertising_sets_.begin(), advertising_sets_.end(), [](const auto& set) {
      return set.second.in_use;
    });
  }

  int get_advertiser_reg_id(AdvertiserId advertiser_id) {
    return id_map_[advertiser_id];
  }

  AdvertisingApiType get_advertising_api_type() const {
    return advertising_api_type_;
  }

  void register_advertising_callback(AdvertisingCallback* advertising_callback) {
    advertising_callbacks_ = advertising_callback;
  }

  void multi_advertising_state_change(hci::VendorSpecificEventView event) {
    auto view = hci::LEAdvertiseStateChangeEventView::Create(event);
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");

    auto advertiser_id = view.GetAdvertisingInstance();

    log::info(
        "Instance: 0x{:x} StateChangeReason: {} Handle: 0x{:x} Address: {}",
        advertiser_id,
        VseStateChangeReasonText(view.GetStateChangeReason()),
        view.GetConnectionHandle(),
        advertising_sets_[view.GetAdvertisingInstance()].current_address.ToString());

    if (view.GetStateChangeReason() == VseStateChangeReason::CONNECTION_RECEIVED) {
      acl_manager_->OnAdvertisingSetTerminated(
          ErrorCode::SUCCESS,
          view.GetConnectionHandle(),
          advertiser_id,
          advertising_sets_[advertiser_id].current_address,
          advertising_sets_[advertiser_id].discoverable);

      enabled_sets_[advertiser_id].advertising_handle_ = kInvalidHandle;

      if (!advertising_sets_[advertiser_id].directed) {
        // TODO(250666237) calculate remaining duration and advertising events
        log::info("Resuming advertising, since not directed");
        enable_advertiser(advertiser_id, true, 0, 0);
      }
    }
  }

  void handle_event(LeMetaEventView event) {
    switch (event.GetSubeventCode()) {
      case hci::SubeventCode::SCAN_REQUEST_RECEIVED:
        handle_scan_request(LeScanRequestReceivedView::Create(event));
        break;
      case hci::SubeventCode::ADVERTISING_SET_TERMINATED:
        handle_set_terminated(LeAdvertisingSetTerminatedView::Create(event));
        break;
      default:
        log::info("Unknown subevent in scanner {}", hci::SubeventCodeText(event.GetSubeventCode()));
    }
  }

  void handle_scan_request(LeScanRequestReceivedView event_view) {
    if (!event_view.IsValid()) {
      log::info("Dropping invalid scan request event");
      return;
    }
    registered_handler_->Post(
        common::BindOnce(scan_callback_, event_view.GetScannerAddress(), event_view.GetScannerAddressType()));
  }

  void handle_set_terminated(LeAdvertisingSetTerminatedView event_view) {
    if (!event_view.IsValid()) {
      log::info("Dropping invalid advertising event");
      return;
    }

    auto status = event_view.GetStatus();
    log::verbose("Received LE Advertising Set Terminated with status {}", ErrorCodeText(status));

    /* The Bluetooth Core 5.3 specification clearly states that this event
     * shall not be sent when the Host disables the advertising set. So in
     * case of HCI_ERROR_CANCELLED_BY_HOST, just ignore the event.
     */
    if (status == ErrorCode::OPERATION_CANCELLED_BY_HOST) {
      log::warn("Unexpected advertising set terminated event status: {}", ErrorCodeText(status));
      return;
    }

    uint8_t advertiser_id = event_view.GetAdvertisingHandle();

    bool was_rotating_address = false;
    if (advertising_sets_[advertiser_id].address_rotation_alarm != nullptr) {
      was_rotating_address = true;
      advertising_sets_[advertiser_id].address_rotation_alarm->Cancel();
      advertising_sets_[advertiser_id].address_rotation_alarm.reset();
    }
    enabled_sets_[advertiser_id].advertising_handle_ = kInvalidHandle;

    AddressWithType advertiser_address = advertising_sets_[event_view.GetAdvertisingHandle()].current_address;
    bool is_discoverable = advertising_sets_[event_view.GetAdvertisingHandle()].discoverable;

    acl_manager_->OnAdvertisingSetTerminated(
        status,
        event_view.GetConnectionHandle(),
        advertiser_id,
        advertiser_address,
        is_discoverable);

    if (status == ErrorCode::LIMIT_REACHED || status == ErrorCode::ADVERTISING_TIMEOUT) {
      if (id_map_[advertiser_id] == kIdLocal) {
        if (!advertising_sets_[advertiser_id].timeout_callback.is_null()) {
          std::move(advertising_sets_[advertiser_id].timeout_callback).Run((uint8_t)status);
          advertising_sets_[advertiser_id].timeout_callback.Reset();
        }
      } else {
        advertising_callbacks_->OnAdvertisingEnabled(advertiser_id, false, (uint8_t)status);
      }
      return;
    }

    if (!advertising_sets_[advertiser_id].directed) {
      // TODO calculate remaining duration and advertising events
      if (advertising_sets_[advertiser_id].duration == 0 &&
          advertising_sets_[advertiser_id].max_extended_advertising_events == 0) {
        log::info("Reenable advertising");
        if (was_rotating_address) {
          advertising_sets_[advertiser_id].address_rotation_alarm = std::make_unique<os::Alarm>(module_handler_);
          advertising_sets_[advertiser_id].address_rotation_alarm->Schedule(
              common::BindOnce(
                  &impl::set_advertising_set_random_address_on_timer, common::Unretained(this), advertiser_id),
              le_address_manager_->GetNextPrivateAddressIntervalMs());
        }
        enable_advertiser(advertiser_id, true, 0, 0);
      }
    }
  }

  AdvertiserId allocate_advertiser() {
    // number of LE_MULTI_ADVT start from 1
    AdvertiserId id = advertising_api_type_ == AdvertisingApiType::ANDROID_HCI ? 1 : 0;
    while (id < num_instances_ && advertising_sets_.count(id) != 0) {
      id++;
    }
    if (id == num_instances_) {
      log::warn("Number of max instances {} reached", (uint16_t)num_instances_);
      return kInvalidId;
    }
    advertising_sets_[id].in_use = true;
    return id;
  }

  void remove_advertiser(AdvertiserId advertiser_id) {
    stop_advertising(advertiser_id);
    std::unique_lock lock(id_mutex_);
    if (advertising_sets_.count(advertiser_id) == 0) {
      return;
    }
    if (advertising_api_type_ == AdvertisingApiType::EXTENDED) {
      le_advertising_interface_->EnqueueCommand(
          hci::LeRemoveAdvertisingSetBuilder::Create(advertiser_id),
          module_handler_->BindOnce(check_complete<LeRemoveAdvertisingSetCompleteView>));

      if (advertising_sets_[advertiser_id].address_rotation_alarm != nullptr) {
        advertising_sets_[advertiser_id].address_rotation_alarm->Cancel();
        advertising_sets_[advertiser_id].address_rotation_alarm.reset();
      }
    }
    advertising_sets_.erase(advertiser_id);
    if (advertising_sets_.empty() && address_manager_registered) {
      le_address_manager_->Unregister(this);
      address_manager_registered = false;
      paused = false;
    }
  }

  /// Generates an address for the advertiser
  AddressWithType new_advertiser_address(AdvertiserId id) {
    switch (advertising_sets_[id].address_type) {
      case AdvertiserAddressType::PUBLIC:
        if (le_address_manager_->GetAddressPolicy() ==
            LeAddressManager::AddressPolicy::USE_STATIC_ADDRESS) {
          return le_address_manager_->GetInitiatorAddress();
        } else {
          return AddressWithType(controller_->GetMacAddress(), AddressType::PUBLIC_DEVICE_ADDRESS);
        }
      case AdvertiserAddressType::RESOLVABLE_RANDOM:
        if (advertising_api_type_ == AdvertisingApiType::LEGACY) {
          // we reuse the initiator address if we are a legacy advertiser using privacy,
          // since there's no way to use a different address
          return le_address_manager_->GetInitiatorAddress();
        }
        return le_address_manager_->NewResolvableAddress();
      case AdvertiserAddressType::NONRESOLVABLE_RANDOM:
        return le_address_manager_->NewNonResolvableAddress();
      default:
        log::fatal("unreachable");
    }
  }

  void create_advertiser(
      int reg_id,
      const AdvertisingConfig config,
      common::Callback<void(Address, AddressType)> scan_callback,
      common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback,
      os::Handler* handler) {
    AdvertiserId id = allocate_advertiser();
    if (id == kInvalidId) {
      log::warn("Number of max instances reached");
      start_advertising_fail(reg_id, AdvertisingCallback::AdvertisingStatus::TOO_MANY_ADVERTISERS);
      return;
    }

    create_advertiser_with_id(reg_id, id, config, scan_callback, set_terminated_callback, handler);
  }

  void create_advertiser_with_id(
      int reg_id,
      AdvertiserId id,
      const AdvertisingConfig config,
      common::Callback<void(Address, AddressType)> scan_callback,
      common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback,
      os::Handler* handler) {
    // check advertising data is valid before start advertising
    if (!check_advertising_data(config.advertisement, config.connectable && config.discoverable) ||
        !check_advertising_data(config.scan_response, false)) {
      advertising_callbacks_->OnAdvertisingSetStarted(
          reg_id, id, le_physical_channel_tx_power_, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
      return;
    }

    id_map_[id] = reg_id;
    advertising_sets_[id].scan_callback = scan_callback;
    advertising_sets_[id].set_terminated_callback = set_terminated_callback;
    advertising_sets_[id].handler = handler;

    if (!address_manager_registered) {
      le_address_manager_->Register(this);
      address_manager_registered = true;
    }

    if (com::android::bluetooth::flags::nrpa_non_connectable_adv() && !config.connectable) {
      advertising_sets_[id].address_type = GetAdvertiserAddressTypeNonConnectable(
          config.requested_advertiser_address_type, le_address_manager_->GetAddressPolicy());
    } else {
      advertising_sets_[id].address_type = GetAdvertiserAddressTypeFromRequestedTypeAndPolicy(
          config.requested_advertiser_address_type, le_address_manager_->GetAddressPolicy());
    }
    advertising_sets_[id].current_address = new_advertiser_address(id);
    set_parameters(id, config);

    switch (advertising_api_type_) {
      case (AdvertisingApiType::LEGACY): {
        if (config.advertising_type == AdvertisingType::ADV_IND ||
            config.advertising_type == AdvertisingType::ADV_NONCONN_IND) {
          set_data(id, true, config.scan_response);
        }
        set_data(id, false, config.advertisement);
        if (!paused) {
          enable_advertiser(id, true, 0, 0);
        } else {
          enabled_sets_[id].advertising_handle_ = id;
        }
      } break;
      case (AdvertisingApiType::ANDROID_HCI): {
        if (config.advertising_type == AdvertisingType::ADV_IND ||
            config.advertising_type == AdvertisingType::ADV_NONCONN_IND) {
          set_data(id, true, config.scan_response);
        }
        set_data(id, false, config.advertisement);
        if (advertising_sets_[id].address_type != AdvertiserAddressType::PUBLIC) {
          le_advertising_interface_->EnqueueCommand(
              hci::LeMultiAdvtSetRandomAddrBuilder::Create(
                  advertising_sets_[id].current_address.GetAddress(), id),
              module_handler_->BindOnce(check_complete<LeMultiAdvtCompleteView>));
        }
        if (!paused) {
          enable_advertiser(id, true, 0, 0);
        } else {
          enabled_sets_[id].advertising_handle_ = id;
        }
      } break;
      case (AdvertisingApiType::EXTENDED): {
        log::warn("Unexpected AdvertisingApiType EXTENDED");
      } break;
    }
  }

  void start_advertising(
      AdvertiserId id,
      const AdvertisingConfig config,
      uint16_t duration,
      base::OnceCallback<void(uint8_t /* status */)> status_callback,
      base::OnceCallback<void(uint8_t /* status */)> timeout_callback,
      const common::Callback<void(Address, AddressType)> scan_callback,
      const common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback,
      os::Handler* handler) {
    advertising_sets_[id].status_callback = std::move(status_callback);
    advertising_sets_[id].timeout_callback = std::move(timeout_callback);

    // legacy start_advertising use default jni client id
    create_extended_advertiser_with_id(
        kAdvertiserClientIdJni,
        kIdLocal,
        id,
        config,
        scan_callback,
        set_terminated_callback,
        duration,
        0,
        handler);
  }

  void create_extended_advertiser(
      uint8_t client_id,
      int reg_id,
      const AdvertisingConfig config,
      common::Callback<void(Address, AddressType)> scan_callback,
      common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback,
      uint16_t duration,
      uint8_t max_ext_adv_events,
      os::Handler* handler) {
    AdvertiserId id = allocate_advertiser();
    if (id == kInvalidId) {
      log::warn("Number of max instances reached");
      start_advertising_fail(reg_id, AdvertisingCallback::AdvertisingStatus::TOO_MANY_ADVERTISERS);
      return;
    }
    create_extended_advertiser_with_id(
        client_id,
        reg_id,
        id,
        config,
        scan_callback,
        set_terminated_callback,
        duration,
        max_ext_adv_events,
        handler);
  }

  void create_extended_advertiser_with_id(
      uint8_t client_id,
      int reg_id,
      AdvertiserId id,
      const AdvertisingConfig config,
      common::Callback<void(Address, AddressType)> scan_callback,
      common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback,
      uint16_t duration,
      uint8_t max_ext_adv_events,
      os::Handler* handler) {
    id_map_[id] = reg_id;

    if (advertising_api_type_ != AdvertisingApiType::EXTENDED) {
      create_advertiser_with_id(
          reg_id, id, config, scan_callback, set_terminated_callback, handler);
      return;
    }

    // check extended advertising data is valid before start advertising
    if (!check_extended_advertising_data(
            config.advertisement, config.connectable && config.discoverable) ||
        !check_extended_advertising_data(config.scan_response, false)) {
      advertising_callbacks_->OnAdvertisingSetStarted(
          reg_id, id, le_physical_channel_tx_power_, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
      return;
    }

    if (!address_manager_registered) {
      le_address_manager_->Register(this);
      address_manager_registered = true;
    }

    advertising_sets_[id].scan_callback = scan_callback;
    advertising_sets_[id].set_terminated_callback = set_terminated_callback;
    advertising_sets_[id].duration = duration;
    advertising_sets_[id].max_extended_advertising_events = max_ext_adv_events;
    advertising_sets_[id].handler = handler;
    if (com::android::bluetooth::flags::nrpa_non_connectable_adv() && !config.connectable) {
      advertising_sets_[id].address_type = GetAdvertiserAddressTypeNonConnectable(
          config.requested_advertiser_address_type, le_address_manager_->GetAddressPolicy());
    } else {
      advertising_sets_[id].address_type = GetAdvertiserAddressTypeFromRequestedTypeAndPolicy(
          config.requested_advertiser_address_type, le_address_manager_->GetAddressPolicy());
    }
    advertising_sets_[id].current_address = new_advertiser_address(id);

    set_parameters(id, config);

    if (advertising_sets_[id].current_address.GetAddressType() !=
        AddressType::PUBLIC_DEVICE_ADDRESS) {
      // if we aren't using the public address type at the HCI level, we need to set the random
      // address
      le_advertising_interface_->EnqueueCommand(
          hci::LeSetAdvertisingSetRandomAddressBuilder::Create(
              id, advertising_sets_[id].current_address.GetAddress()),
          module_handler_->BindOnceOn(
              this,
              &impl::on_set_advertising_set_random_address_complete<
                  LeSetAdvertisingSetRandomAddressCompleteView>,
              id,
              advertising_sets_[id].current_address));

      bool leaudio_requested_nrpa = false;
      if (client_id == kAdvertiserClientIdLeAudio &&
          advertising_sets_[id].address_type == AdvertiserAddressType::NONRESOLVABLE_RANDOM) {
        log::info(
            "Advertiser started by le audio client with address type: {}",
            advertising_sets_[id].address_type);
        leaudio_requested_nrpa = true;
      }

      // but we only rotate if the AdvertiserAddressType is non-public
      // or non-rpa requested by leaudio(since static random addresses don't rotate)
      if (advertising_sets_[id].address_type != AdvertiserAddressType::PUBLIC &&
          !leaudio_requested_nrpa) {
        // start timer for random address
        advertising_sets_[id].address_rotation_alarm = std::make_unique<os::Alarm>(module_handler_);
        advertising_sets_[id].address_rotation_alarm->Schedule(
            common::BindOnce(
                &impl::set_advertising_set_random_address_on_timer, common::Unretained(this), id),
            le_address_manager_->GetNextPrivateAddressIntervalMs());
      }
    }
    if (config.advertising_type == AdvertisingType::ADV_IND ||
        config.advertising_type == AdvertisingType::ADV_NONCONN_IND) {
      set_data(id, true, config.scan_response);
    }
    set_data(id, false, config.advertisement);

    if (!config.periodic_data.empty()) {
      set_periodic_parameter(id, config.periodic_advertising_parameters);
      set_periodic_data(id, config.periodic_data);
      enable_periodic_advertising(
          id, config.periodic_advertising_parameters.enable, config.periodic_advertising_parameters.include_adi);
    }

    if (!paused) {
      enable_advertiser(id, true, duration, max_ext_adv_events);
    } else {
      EnabledSet curr_set;
      curr_set.advertising_handle_ = id;
      curr_set.duration_ = duration;
      curr_set.max_extended_advertising_events_ = max_ext_adv_events;
      std::vector<EnabledSet> enabled_sets = {curr_set};
      enabled_sets_[id] = curr_set;
    }
  }

  void stop_advertising(AdvertiserId advertiser_id) {
    if (advertising_sets_.find(advertiser_id) == advertising_sets_.end()) {
      log::info("Unknown advertising set {}", advertiser_id);
      return;
    }
    EnabledSet curr_set;
    curr_set.advertising_handle_ = advertiser_id;
    std::vector<EnabledSet> enabled_vector{curr_set};

    // If advertising or periodic advertising on the advertising set is enabled,
    // then the Controller will return the error code Command Disallowed (0x0C).
    // Thus, we should disable it before removing it.
    switch (advertising_api_type_) {
      case (AdvertisingApiType::LEGACY):
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
            module_handler_->BindOnce(check_complete<LeSetAdvertisingEnableCompleteView>));
        break;
      case (AdvertisingApiType::ANDROID_HCI):
        le_advertising_interface_->EnqueueCommand(
            hci::LeMultiAdvtSetEnableBuilder::Create(Enable::DISABLED, advertiser_id),
            module_handler_->BindOnce(check_complete<LeMultiAdvtCompleteView>));
        break;
      case (AdvertisingApiType::EXTENDED): {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::DISABLED, enabled_vector),
            module_handler_->BindOnce(check_complete<LeSetExtendedAdvertisingEnableCompleteView>));

        // Only set periodic advertising if supported.
        if (controller_->SupportsBlePeriodicAdvertising()) {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetPeriodicAdvertisingEnableBuilder::Create(false, false, advertiser_id),
              module_handler_->BindOnce(
                  check_complete<LeSetPeriodicAdvertisingEnableCompleteView>));
        }
      } break;
    }

    std::unique_lock lock(id_mutex_);
    enabled_sets_[advertiser_id].advertising_handle_ = kInvalidHandle;
  }

  void rotate_advertiser_address(AdvertiserId advertiser_id) {
    if (advertising_api_type_ == AdvertisingApiType::EXTENDED) {
      AddressWithType address_with_type = new_advertiser_address(advertiser_id);
      le_advertising_interface_->EnqueueCommand(
          hci::LeSetAdvertisingSetRandomAddressBuilder::Create(advertiser_id, address_with_type.GetAddress()),
          module_handler_->BindOnceOn(
              this,
              &impl::on_set_advertising_set_random_address_complete<LeSetAdvertisingSetRandomAddressCompleteView>,
              advertiser_id,
              address_with_type));
    }
  }

  void set_advertising_set_random_address_on_timer(AdvertiserId advertiser_id) {
    // This function should only be trigger by enabled advertising set or IRK rotation
    if (enabled_sets_[advertiser_id].advertising_handle_ == kInvalidHandle) {
      if (advertising_sets_[advertiser_id].address_rotation_alarm != nullptr) {
        advertising_sets_[advertiser_id].address_rotation_alarm->Cancel();
        advertising_sets_[advertiser_id].address_rotation_alarm.reset();
      }
      return;
    }

    // TODO handle duration and max_extended_advertising_events_
    EnabledSet curr_set;
    curr_set.advertising_handle_ = advertiser_id;
    curr_set.duration_ = advertising_sets_[advertiser_id].duration;
    curr_set.max_extended_advertising_events_ = advertising_sets_[advertiser_id].max_extended_advertising_events;
    std::vector<EnabledSet> enabled_sets = {curr_set};

    // For connectable advertising, we should disable it first
    if (advertising_sets_[advertiser_id].connectable) {
      le_advertising_interface_->EnqueueCommand(
          hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::DISABLED, enabled_sets),
          module_handler_->BindOnce(check_complete<LeSetExtendedAdvertisingEnableCompleteView>));
    }

    rotate_advertiser_address(advertiser_id);

    // If we are paused, we will be enabled in OnResume(), so don't resume now.
    // Note that OnResume() can never re-enable us while we are changing our address, since the
    // DISABLED and ENABLED commands are enqueued synchronously, so OnResume() doesn't need an
    // analogous check.
    if (advertising_sets_[advertiser_id].connectable && !paused) {
      le_advertising_interface_->EnqueueCommand(
          hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::ENABLED, enabled_sets),
          module_handler_->BindOnce(check_complete<LeSetExtendedAdvertisingEnableCompleteView>));
    }

    advertising_sets_[advertiser_id].address_rotation_alarm->Schedule(
        common::BindOnce(&impl::set_advertising_set_random_address_on_timer, common::Unretained(this), advertiser_id),
        le_address_manager_->GetNextPrivateAddressIntervalMs());
  }

  void register_advertiser(
      common::ContextualOnceCallback<void(uint8_t /* inst_id */, uint8_t /* status */)> callback) {
    AdvertiserId id = allocate_advertiser();
    if (id == kInvalidId) {
      callback(kInvalidId, AdvertisingCallback::AdvertisingStatus::TOO_MANY_ADVERTISERS);
    } else {
      callback(id, AdvertisingCallback::AdvertisingStatus::SUCCESS);
    }
  }

  void get_own_address(AdvertiserId advertiser_id) {
    if (advertising_sets_.find(advertiser_id) == advertising_sets_.end()) {
      log::info("Unknown advertising id {}", advertiser_id);
      return;
    }
    auto current_address = advertising_sets_[advertiser_id].current_address;
    advertising_callbacks_->OnOwnAddressRead(
        advertiser_id, static_cast<uint8_t>(current_address.GetAddressType()), current_address.GetAddress());
  }

  void set_parameters(AdvertiserId advertiser_id, AdvertisingConfig config) {
    config.tx_power = get_tx_power_after_calibration(static_cast<int8_t>(config.tx_power));
    advertising_sets_[advertiser_id].is_legacy = config.legacy_pdus;
    advertising_sets_[advertiser_id].connectable = config.connectable;
    advertising_sets_[advertiser_id].discoverable = config.discoverable;
    advertising_sets_[advertiser_id].tx_power = config.tx_power;
    advertising_sets_[advertiser_id].directed = config.directed;

    // based on logic in new_advertiser_address
    auto own_address_type = static_cast<OwnAddressType>(
        advertising_sets_[advertiser_id].current_address.GetAddressType());

    switch (advertising_api_type_) {
      case (AdvertisingApiType::LEGACY): {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetAdvertisingParametersBuilder::Create(
                config.interval_min,
                config.interval_max,
                config.advertising_type,
                own_address_type,
                config.peer_address_type,
                config.peer_address,
                config.channel_map,
                config.filter_policy),
            module_handler_->BindOnceOn(
                this,
                &impl::check_status_with_id<LeSetAdvertisingParametersCompleteView>,
                true,
                advertiser_id));
      } break;
      case (AdvertisingApiType::ANDROID_HCI): {
        le_advertising_interface_->EnqueueCommand(
            hci::LeMultiAdvtParamBuilder::Create(
                config.interval_min,
                config.interval_max,
                config.advertising_type,
                own_address_type,
                advertising_sets_[advertiser_id].current_address.GetAddress(),
                config.peer_address_type,
                config.peer_address,
                config.channel_map,
                config.filter_policy,
                advertiser_id,
                config.tx_power),
            module_handler_->BindOnceOn(
                this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, true, advertiser_id));
      } break;
      case (AdvertisingApiType::EXTENDED): {
        // sid must be in range 0x00 to 0x0F. Since no controller supports more than
        // 16 advertisers, it's safe to make sid equal to id.
        config.sid = advertiser_id % kAdvertisingSetIdMask;

        if (config.legacy_pdus) {
          LegacyAdvertisingEventProperties legacy_properties = LegacyAdvertisingEventProperties::ADV_IND;
          if (config.connectable && config.directed) {
            if (config.high_duty_directed_connectable) {
              legacy_properties = LegacyAdvertisingEventProperties::ADV_DIRECT_IND_HIGH;
            } else {
              legacy_properties = LegacyAdvertisingEventProperties::ADV_DIRECT_IND_LOW;
            }
          }
          if (config.scannable && !config.connectable) {
            legacy_properties = LegacyAdvertisingEventProperties::ADV_SCAN_IND;
          }
          if (!config.scannable && !config.connectable) {
            legacy_properties = LegacyAdvertisingEventProperties::ADV_NONCONN_IND;
          }

          le_advertising_interface_->EnqueueCommand(
              LeSetExtendedAdvertisingParametersLegacyBuilder::Create(
                  advertiser_id,
                  legacy_properties,
                  config.interval_min,
                  config.interval_max,
                  config.channel_map,
                  own_address_type,
                  config.peer_address_type,
                  config.peer_address,
                  config.filter_policy,
                  config.tx_power,
                  config.sid,
                  config.enable_scan_request_notifications),
              module_handler_->BindOnceOn(
                  this,
                  &impl::on_set_extended_advertising_parameters_complete<
                      LeSetExtendedAdvertisingParametersCompleteView>,
                  advertiser_id));
        } else {
          AdvertisingEventProperties extended_properties;
          extended_properties.connectable_ = config.connectable;
          extended_properties.scannable_ = config.scannable;
          extended_properties.directed_ = config.directed;
          extended_properties.high_duty_cycle_ = config.high_duty_directed_connectable;
          extended_properties.legacy_ = false;
          extended_properties.anonymous_ = config.anonymous;
          extended_properties.tx_power_ = config.include_tx_power;

          le_advertising_interface_->EnqueueCommand(
              hci::LeSetExtendedAdvertisingParametersBuilder::Create(
                  advertiser_id,
                  extended_properties,
                  config.interval_min,
                  config.interval_max,
                  config.channel_map,
                  own_address_type,
                  config.peer_address_type,
                  config.peer_address,
                  config.filter_policy,
                  config.tx_power,
                  (config.use_le_coded_phy ? PrimaryPhyType::LE_CODED : PrimaryPhyType::LE_1M),
                  config.secondary_max_skip,
                  config.secondary_advertising_phy,
                  config.sid,
                  config.enable_scan_request_notifications),
              module_handler_->BindOnceOn(
                  this,
                  &impl::on_set_extended_advertising_parameters_complete<
                      LeSetExtendedAdvertisingParametersCompleteView>,
                  advertiser_id));
        }
      } break;
    }
  }

  bool data_has_flags(std::vector<GapData> data) {
    for (auto& gap_data : data) {
      if (gap_data.data_type_ == GapDataType::FLAGS) {
        return true;
      }
    }
    return false;
  }

  bool check_advertising_data(std::vector<GapData> data, bool include_flag) {
    uint16_t data_len = 0;
    // check data size
    for (size_t i = 0; i < data.size(); i++) {
      data_len += data[i].size();
    }

    // The Flags data type shall be included when any of the Flag bits are non-zero and the
    // advertising packet is connectable and discoverable. It will be added by set_data() function,
    // we should count it here.
    if (include_flag && !data_has_flags(data)) {
      data_len += kLenOfFlags;
    }

    if (data_len > le_maximum_advertising_data_length_) {
      log::warn(
          "advertising data len {} exceeds le_maximum_advertising_data_length_ {}",
          data_len,
          le_maximum_advertising_data_length_);
      return false;
    }
    return true;
  };

  bool check_extended_advertising_data(std::vector<GapData> data, bool include_flag) {
    uint16_t data_len = 0;
    uint16_t data_limit = com::android::bluetooth::flags::divide_long_single_gap_data()
                              ? kLeMaximumGapDataLength
                              : kLeMaximumFragmentLength;
    // check data size
    for (size_t i = 0; i < data.size(); i++) {
      if (data[i].size() > data_limit) {
        log::warn("AD data len shall not greater than {}", data_limit);
        return false;
      }
      data_len += data[i].size();
    }

    // The Flags data type shall be included when any of the Flag bits are non-zero and the
    // advertising packet is connectable and discoverable. It will be added by set_data() function,
    // we should count it here.
    if (include_flag && !data_has_flags(data)) {
      data_len += kLenOfFlags;
    }

    if (data_len > le_maximum_advertising_data_length_) {
      log::warn(
          "advertising data len {} exceeds le_maximum_advertising_data_length_ {}",
          data_len,
          le_maximum_advertising_data_length_);
      return false;
    }
    return true;
  };

  void set_data(AdvertiserId advertiser_id, bool set_scan_rsp, std::vector<GapData> data) {
    // The Flags data type shall be included when any of the Flag bits are non-zero and the
    // advertising packet is connectable and discoverable.
    if (!set_scan_rsp && advertising_sets_[advertiser_id].connectable &&
        advertising_sets_[advertiser_id].discoverable && !data_has_flags(data)) {
      GapData gap_data;
      gap_data.data_type_ = GapDataType::FLAGS;
      if (advertising_sets_[advertiser_id].duration == 0) {
        gap_data.data_.push_back(static_cast<uint8_t>(AdvertisingFlag::LE_GENERAL_DISCOVERABLE));
      } else {
        gap_data.data_.push_back(static_cast<uint8_t>(AdvertisingFlag::LE_LIMITED_DISCOVERABLE));
      }
      data.insert(data.begin(), gap_data);
    }

    // Find and fill TX Power with the correct value.
    for (auto& gap_data : data) {
      if (gap_data.data_type_ == GapDataType::TX_POWER_LEVEL) {
        gap_data.data_[0] = advertising_sets_[advertiser_id].tx_power;
        break;
      }
    }

    if (advertising_api_type_ != AdvertisingApiType::EXTENDED && !check_advertising_data(data, false)) {
      if (set_scan_rsp) {
        advertising_callbacks_->OnScanResponseDataSet(
            advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
      } else {
        advertising_callbacks_->OnAdvertisingDataSet(
            advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
      }
      return;
    }

    switch (advertising_api_type_) {
      case (AdvertisingApiType::LEGACY): {
        if (set_scan_rsp) {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetScanResponseDataBuilder::Create(data),
              module_handler_->BindOnceOn(
                  this,
                  &impl::check_status_with_id<LeSetScanResponseDataCompleteView>,
                  true,
                  advertiser_id));
        } else {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetAdvertisingDataBuilder::Create(data),
              module_handler_->BindOnceOn(
                  this,
                  &impl::check_status_with_id<LeSetAdvertisingDataCompleteView>,
                  true,
                  advertiser_id));
        }
      } break;
      case (AdvertisingApiType::ANDROID_HCI): {
        if (set_scan_rsp) {
          le_advertising_interface_->EnqueueCommand(
              hci::LeMultiAdvtSetScanRespBuilder::Create(data, advertiser_id),
              module_handler_->BindOnceOn(
                  this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, true, advertiser_id));
        } else {
          le_advertising_interface_->EnqueueCommand(
              hci::LeMultiAdvtSetDataBuilder::Create(data, advertiser_id),
              module_handler_->BindOnceOn(
                  this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, true, advertiser_id));
        }
      } break;
      case (AdvertisingApiType::EXTENDED): {
        uint16_t data_len = 0;
        bool divide_gap_flag = com::android::bluetooth::flags::divide_long_single_gap_data();
        // check data size
        for (size_t i = 0; i < data.size(); i++) {
          uint16_t data_limit =
              divide_gap_flag ? kLeMaximumGapDataLength : kLeMaximumFragmentLength;
          if (data[i].size() > data_limit) {
            log::warn("AD data len shall not greater than {}", data_limit);
            if (advertising_callbacks_ != nullptr) {
              if (set_scan_rsp) {
                advertising_callbacks_->OnScanResponseDataSet(
                    advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
              } else {
                advertising_callbacks_->OnAdvertisingDataSet(
                    advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
              }
            }
            return;
          }
          data_len += data[i].size();
        }

        int maxDataLength =
            (com::android::bluetooth::flags::ble_check_data_length_on_legacy_advertising() &&
             advertising_sets_[advertiser_id].is_legacy)
                ? kLeMaximumLegacyAdvertisingDataLength
                : le_maximum_advertising_data_length_;

        if (data_len > maxDataLength) {
          log::warn("advertising data len {} exceeds maxDataLength {}", data_len, maxDataLength);
          if (advertising_callbacks_ != nullptr) {
            if (set_scan_rsp) {
              advertising_callbacks_->OnScanResponseDataSet(
                  advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
            } else {
              advertising_callbacks_->OnAdvertisingDataSet(
                  advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
            }
          }
          return;
        }

        if (data_len <= kLeMaximumFragmentLength) {
          send_data_fragment(advertiser_id, set_scan_rsp, 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(
                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);
                operation = Operation::INTERMEDIATE_FRAGMENT;
                sub_data_len = 0;
                sub_data.clear();
              }
              sub_data.push_back(data[i]);
              sub_data_len += data[i].size();
            }
            send_data_fragment(advertiser_id, set_scan_rsp, sub_data, Operation::LAST_FRAGMENT);
          }
        }
      } break;
    }
  }

  void send_data_fragment(
      AdvertiserId advertiser_id, bool set_scan_rsp, std::vector<GapData> data, Operation operation) {
    if (com::android::bluetooth::flags::divide_long_single_gap_data()) {
      // For first and intermediate fragment, do not trigger advertising_callbacks_.
      bool send_callback =
          (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT);
      if (set_scan_rsp) {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedScanResponseDataBuilder::Create(
                advertiser_id, operation, kFragment_preference, data),
            module_handler_->BindOnceOn(
                this,
                &impl::check_status_with_id<LeSetExtendedScanResponseDataCompleteView>,
                send_callback,
                advertiser_id));
      } else {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedAdvertisingDataBuilder::Create(
                advertiser_id, operation, kFragment_preference, data),
            module_handler_->BindOnceOn(
                this,
                &impl::check_status_with_id<LeSetExtendedAdvertisingDataCompleteView>,
                send_callback,
                advertiser_id));
      }
    } else {
      if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) {
        if (set_scan_rsp) {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetExtendedScanResponseDataBuilder::Create(
                  advertiser_id, operation, kFragment_preference, data),
              module_handler_->BindOnceOn(
                  this,
                  &impl::check_status_with_id<LeSetExtendedScanResponseDataCompleteView>,
                  true,
                  advertiser_id));
        } else {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetExtendedAdvertisingDataBuilder::Create(
                  advertiser_id, operation, kFragment_preference, data),
              module_handler_->BindOnceOn(
                  this,
                  &impl::check_status_with_id<LeSetExtendedAdvertisingDataCompleteView>,
                  true,
                  advertiser_id));
        }
      } else {
        // For first and intermediate fragment, do not trigger advertising_callbacks_.
        if (set_scan_rsp) {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetExtendedScanResponseDataBuilder::Create(
                  advertiser_id, operation, kFragment_preference, data),
              module_handler_->BindOnce(check_complete<LeSetExtendedScanResponseDataCompleteView>));
        } else {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetExtendedAdvertisingDataBuilder::Create(
                  advertiser_id, operation, kFragment_preference, data),
              module_handler_->BindOnce(check_complete<LeSetExtendedAdvertisingDataCompleteView>));
        }
      }
    }
  }

  void send_data_fragment_with_raw_builder(
      AdvertiserId advertiser_id,
      bool set_scan_rsp,
      std::unique_ptr<packet::RawBuilder> data,
      Operation operation) {
    // For first and intermediate fragment, do not trigger advertising_callbacks_.
    bool send_callback =
        (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>,
              send_callback,
              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>,
              send_callback,
              advertiser_id));
    }
  }

  void enable_advertiser(
      AdvertiserId advertiser_id, bool enable, uint16_t duration, uint8_t max_extended_advertising_events) {
    EnabledSet curr_set;
    curr_set.advertising_handle_ = advertiser_id;
    curr_set.duration_ = duration;
    curr_set.max_extended_advertising_events_ = max_extended_advertising_events;
    std::vector<EnabledSet> enabled_sets = {curr_set};
    Enable enable_value = enable ? Enable::ENABLED : Enable::DISABLED;

    if (!advertising_sets_.count(advertiser_id)) {
      log::warn("No advertising set with key: {}", advertiser_id);
      return;
    }

    switch (advertising_api_type_) {
      case (AdvertisingApiType::LEGACY): {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetAdvertisingEnableBuilder::Create(enable_value),
            module_handler_->BindOnceOn(
                this,
                &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
                enable,
                enabled_sets,
                true /* trigger callbacks */));
      } break;
      case (AdvertisingApiType::ANDROID_HCI): {
        le_advertising_interface_->EnqueueCommand(
            hci::LeMultiAdvtSetEnableBuilder::Create(enable_value, advertiser_id),
            module_handler_->BindOnceOn(
                this,
                &impl::on_set_advertising_enable_complete<LeMultiAdvtCompleteView>,
                enable,
                enabled_sets,
                true /* trigger callbacks */));
      } break;
      case (AdvertisingApiType::EXTENDED): {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedAdvertisingEnableBuilder::Create(enable_value, enabled_sets),
            module_handler_->BindOnceOn(
                this,
                &impl::on_set_extended_advertising_enable_complete<
                    LeSetExtendedAdvertisingEnableCompleteView>,
                enable,
                enabled_sets,
                true /* trigger callbacks */));
      } break;
    }

    if (enable) {
      enabled_sets_[advertiser_id].advertising_handle_ = advertiser_id;
      if (advertising_api_type_ == AdvertisingApiType::EXTENDED) {
        enabled_sets_[advertiser_id].duration_ = duration;
        enabled_sets_[advertiser_id].max_extended_advertising_events_ =
            max_extended_advertising_events;
      }

      advertising_sets_[advertiser_id].duration = duration;
      advertising_sets_[advertiser_id].max_extended_advertising_events = max_extended_advertising_events;
    } else {
      enabled_sets_[advertiser_id].advertising_handle_ = kInvalidHandle;
      if (advertising_sets_[advertiser_id].address_rotation_alarm != nullptr) {
        advertising_sets_[advertiser_id].address_rotation_alarm->Cancel();
        advertising_sets_[advertiser_id].address_rotation_alarm.reset();
      }
    }
  }

  void set_periodic_parameter(
      AdvertiserId advertiser_id, PeriodicAdvertisingParameters periodic_advertising_parameters) {
    uint8_t include_tx_power = periodic_advertising_parameters.properties >>
                               PeriodicAdvertisingParameters::AdvertisingProperty::INCLUDE_TX_POWER;

    le_advertising_interface_->EnqueueCommand(
        hci::LeSetPeriodicAdvertisingParametersBuilder::Create(
            advertiser_id,
            periodic_advertising_parameters.min_interval,
            periodic_advertising_parameters.max_interval,
            include_tx_power),
        module_handler_->BindOnceOn(
            this,
            &impl::check_status_with_id<LeSetPeriodicAdvertisingParametersCompleteView>,
            true,
            advertiser_id));
  }

  void set_periodic_data(AdvertiserId advertiser_id, std::vector<GapData> data) {
    uint16_t data_len = 0;
    bool divide_gap_flag = com::android::bluetooth::flags::divide_long_single_gap_data();
    // check data size
    for (size_t i = 0; i < data.size(); i++) {
      uint16_t data_limit = divide_gap_flag ? kLeMaximumGapDataLength : kLeMaximumFragmentLength;
      if (data[i].size() > data_limit) {
        log::warn("AD data len shall not greater than {}", data_limit);
        if (advertising_callbacks_ != nullptr) {
          advertising_callbacks_->OnPeriodicAdvertisingDataSet(
              advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
        }
        return;
      }
      data_len += data[i].size();
    }

    if (data_len > le_maximum_advertising_data_length_) {
      log::warn(
          "advertising data len exceeds le_maximum_advertising_data_length_ {}",
          le_maximum_advertising_data_length_);
      if (advertising_callbacks_ != nullptr) {
        advertising_callbacks_->OnPeriodicAdvertisingDataSet(
            advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
      }
      return;
    }

    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);
            operation = Operation::INTERMEDIATE_FRAGMENT;
            sub_data_len = 0;
            sub_data.clear();
          }
          sub_data.push_back(data[i]);
          sub_data_len += data[i].size();
        }
        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 (com::android::bluetooth::flags::divide_long_single_gap_data()) {
      // For first and intermediate fragment, do not trigger advertising_callbacks_.
      bool send_callback =
          (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT);
      le_advertising_interface_->EnqueueCommand(
          hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data),
          module_handler_->BindOnceOn(
              this,
              &impl::check_status_with_id<LeSetPeriodicAdvertisingDataCompleteView>,
              send_callback,
              advertiser_id));
    } else {
      if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) {
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data),
            module_handler_->BindOnceOn(
                this,
                &impl::check_status_with_id<LeSetPeriodicAdvertisingDataCompleteView>,
                true,
                advertiser_id));
      } else {
        // For first and intermediate fragment, do not trigger advertising_callbacks_.
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data),
            module_handler_->BindOnce(check_complete<LeSetPeriodicAdvertisingDataCompleteView>));
      }
    }
  }

  void send_periodic_data_fragment_with_raw_builder(
      AdvertiserId advertiser_id, std::unique_ptr<packet::RawBuilder> data, Operation operation) {
    // For first and intermediate fragment, do not trigger advertising_callbacks_.
    bool send_callback =
        (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>,
            send_callback,
            advertiser_id));
  }

  void enable_periodic_advertising(AdvertiserId advertiser_id, bool enable, bool include_adi) {
    if (!controller_->SupportsBlePeriodicAdvertising()) {
      return;
    }

    if (include_adi && !controller_->SupportsBlePeriodicAdvertisingAdi()) {
      include_adi = false;
    }
    le_advertising_interface_->EnqueueCommand(
        hci::LeSetPeriodicAdvertisingEnableBuilder::Create(enable, include_adi, advertiser_id),
        module_handler_->BindOnceOn(
            this,
            &impl::on_set_periodic_advertising_enable_complete<LeSetPeriodicAdvertisingEnableCompleteView>,
            enable,
            advertiser_id));
  }

  void OnPause() override {
    if (!address_manager_registered) {
      log::warn("Unregistered!");
      return;
    }
    paused = true;
    if (!advertising_sets_.empty()) {
      std::vector<EnabledSet> enabled_sets = {};
      for (size_t i = 0; i < enabled_sets_.size(); i++) {
        EnabledSet curr_set = enabled_sets_[i];
        if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
          enabled_sets.push_back(enabled_sets_[i]);
        }
      }

      switch (advertising_api_type_) {
        case (AdvertisingApiType::LEGACY): {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
              module_handler_->BindOnce(check_complete<LeSetAdvertisingEnableCompleteView>));
        } break;
        case (AdvertisingApiType::ANDROID_HCI): {
          for (size_t i = 0; i < enabled_sets_.size(); i++) {
            uint8_t id = enabled_sets_[i].advertising_handle_;
            if (id != kInvalidHandle) {
              le_advertising_interface_->EnqueueCommand(
                  hci::LeMultiAdvtSetEnableBuilder::Create(Enable::DISABLED, id),
                  module_handler_->BindOnce(check_complete<LeMultiAdvtCompleteView>));
            }
          }
        } break;
        case (AdvertisingApiType::EXTENDED): {
          if (enabled_sets.size() != 0) {
            le_advertising_interface_->EnqueueCommand(
                hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::DISABLED, enabled_sets),
                module_handler_->BindOnce(
                    check_complete<LeSetExtendedAdvertisingEnableCompleteView>));
          }
        } break;
      }
    }
    le_address_manager_->AckPause(this);
  }

  void OnResume() override {
    if (!address_manager_registered) {
      log::warn("Unregistered!");
      return;
    }
    paused = false;
    if (!advertising_sets_.empty()) {
      std::vector<EnabledSet> enabled_sets = {};
      for (size_t i = 0; i < enabled_sets_.size(); i++) {
        EnabledSet curr_set = enabled_sets_[i];
        if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
          enabled_sets.push_back(enabled_sets_[i]);
        }
      }

      switch (advertising_api_type_) {
        case (AdvertisingApiType::LEGACY): {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED),
              module_handler_->BindOnceOn(
                  this,
                  &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
                  true,
                  enabled_sets,
                  false /* trigger_callbacks */));
        } break;
        case (AdvertisingApiType::ANDROID_HCI): {
          for (size_t i = 0; i < enabled_sets_.size(); i++) {
            uint8_t id = enabled_sets_[i].advertising_handle_;
            if (id != kInvalidHandle) {
              le_advertising_interface_->EnqueueCommand(
                  hci::LeMultiAdvtSetEnableBuilder::Create(Enable::ENABLED, id),
                  module_handler_->BindOnceOn(
                      this,
                      &impl::on_set_advertising_enable_complete<LeMultiAdvtCompleteView>,
                      true,
                      enabled_sets,
                      false /* trigger_callbacks */));
            }
          }
        } break;
        case (AdvertisingApiType::EXTENDED): {
          if (enabled_sets.size() != 0) {
            le_advertising_interface_->EnqueueCommand(
                hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::ENABLED, enabled_sets),
                module_handler_->BindOnceOn(
                    this,
                    &impl::on_set_extended_advertising_enable_complete<
                        LeSetExtendedAdvertisingEnableCompleteView>,
                    true,
                    enabled_sets,
                    false /* trigger_callbacks */));
          }
        } break;
      }
    }
    le_address_manager_->AckResume(this);
  }

  // Note: this needs to be synchronous (i.e. NOT on a handler) for two reasons:
  // 1. For parity with OnPause() and OnResume()
  // 2. If we don't enqueue our HCI commands SYNCHRONOUSLY, then it is possible that we OnResume() in addressManager
  // before our commands complete. So then our commands reach the HCI layer *after* the resume commands from address
  // manager, which is racey (even if it might not matter).
  //
  // If you are a future developer making this asynchronous, you need to add some kind of ->AckIRKChange() method to the
  // address manager so we can defer resumption to after this completes.
  void NotifyOnIRKChange() override {
    for (size_t i = 0; i < enabled_sets_.size(); i++) {
      if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
        rotate_advertiser_address(i);
      }
    }
  }

  common::Callback<void(Address, AddressType)> scan_callback_;
  common::ContextualCallback<void(ErrorCode, uint16_t, hci::AddressWithType)> set_terminated_callback_{};
  AdvertisingCallback* advertising_callbacks_ = nullptr;
  os::Handler* registered_handler_{nullptr};
  Module* module_;
  os::Handler* module_handler_;
  hci::HciLayer* hci_layer_;
  hci::Controller* controller_;
  uint16_t le_maximum_advertising_data_length_;
  int8_t le_physical_channel_tx_power_ = 0;
  int8_t le_tx_path_loss_comp_ = 0;
  hci::LeAdvertisingInterface* le_advertising_interface_;
  std::map<AdvertiserId, Advertiser> advertising_sets_;
  hci::LeAddressManager* le_address_manager_;
  hci::AclManager* acl_manager_;
  bool address_manager_registered = false;
  bool paused = false;

  std::mutex id_mutex_;
  size_t num_instances_;
  std::vector<hci::EnabledSet> enabled_sets_;
  // map to mapping the id from java layer and advertier id
  std::map<uint8_t, int> id_map_;

  AdvertisingApiType advertising_api_type_{0};

  void on_read_advertising_physical_channel_tx_power(CommandCompleteView view) {
    auto complete_view = LeReadAdvertisingPhysicalChannelTxPowerCompleteView::Create(view);
    if (!complete_view.IsValid()) {
      auto payload = view.GetPayload();
      if (payload.size() == 1 && payload[0] == static_cast<uint8_t>(ErrorCode::UNKNOWN_HCI_COMMAND)) {
        log::info("Unknown command, not setting tx power");
        return;
      }
    }
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info("Got a command complete with status {}", ErrorCodeText(complete_view.GetStatus()));
      return;
    }
    le_physical_channel_tx_power_ = complete_view.GetTransmitPowerLevel();
  }

  template <class View>
  void on_set_advertising_enable_complete(
      bool enable,
      std::vector<EnabledSet> enabled_sets,
      bool trigger_callbacks,
      CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto complete_view = View::Create(view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info("Got a command complete with status {}", ErrorCodeText(complete_view.GetStatus()));
    }

    if (advertising_callbacks_ == nullptr) {
      return;
    }
    for (EnabledSet enabled_set : enabled_sets) {
      bool started = advertising_sets_[enabled_set.advertising_handle_].started;
      uint8_t id = enabled_set.advertising_handle_;
      if (id == kInvalidHandle) {
        continue;
      }

      int reg_id = id_map_[id];
      if (reg_id == kIdLocal) {
        if (!advertising_sets_[enabled_set.advertising_handle_].status_callback.is_null()) {
          std::move(advertising_sets_[enabled_set.advertising_handle_].status_callback).Run(advertising_status);
          advertising_sets_[enabled_set.advertising_handle_].status_callback.Reset();
        }
        continue;
      }

      if (started) {
        if (trigger_callbacks) {
          advertising_callbacks_->OnAdvertisingEnabled(id, enable, advertising_status);
        }
      } else {
        advertising_sets_[enabled_set.advertising_handle_].started = true;
        advertising_callbacks_->OnAdvertisingSetStarted(reg_id, id, le_physical_channel_tx_power_, advertising_status);
      }
    }
  }

  template <class View>
  void on_set_extended_advertising_enable_complete(
      bool enable,
      std::vector<EnabledSet> enabled_sets,
      bool trigger_callbacks,
      CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto complete_view = LeSetExtendedAdvertisingEnableCompleteView::Create(view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info("Got a command complete with status {}", ErrorCodeText(complete_view.GetStatus()));
      advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
    }

    if (advertising_callbacks_ == nullptr) {
      return;
    }

    for (EnabledSet enabled_set : enabled_sets) {
      int8_t tx_power = advertising_sets_[enabled_set.advertising_handle_].tx_power;
      bool started = advertising_sets_[enabled_set.advertising_handle_].started;
      uint8_t id = enabled_set.advertising_handle_;
      if (id == kInvalidHandle) {
        continue;
      }

      int reg_id = id_map_[id];
      if (reg_id == kIdLocal) {
        if (!advertising_sets_[enabled_set.advertising_handle_].status_callback.is_null()) {
          std::move(advertising_sets_[enabled_set.advertising_handle_].status_callback).Run(advertising_status);
          advertising_sets_[enabled_set.advertising_handle_].status_callback.Reset();
        }
        continue;
      }

      if (started) {
        if (trigger_callbacks) {
          advertising_callbacks_->OnAdvertisingEnabled(id, enable, advertising_status);
        }
      } else {
        advertising_sets_[enabled_set.advertising_handle_].started = true;
        advertising_callbacks_->OnAdvertisingSetStarted(reg_id, id, tx_power, advertising_status);
      }
    }
  }

  template <class View>
  void on_set_extended_advertising_parameters_complete(AdvertiserId id, CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto complete_view = LeSetExtendedAdvertisingParametersCompleteView::Create(view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info("Got a command complete with status {}", ErrorCodeText(complete_view.GetStatus()));
      advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
    }
    advertising_sets_[id].tx_power = complete_view.GetSelectedTxPower();

    if (advertising_sets_[id].started && id_map_[id] != kIdLocal) {
      advertising_callbacks_->OnAdvertisingParametersUpdated(id, advertising_sets_[id].tx_power, advertising_status);
    }
  }

  template <class View>
  void on_set_periodic_advertising_enable_complete(bool enable, AdvertiserId id, CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto complete_view = LeSetPeriodicAdvertisingEnableCompleteView::Create(view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info("Got a command complete with status {}", ErrorCodeText(complete_view.GetStatus()));
      advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
    }

    if (advertising_callbacks_ == nullptr || !advertising_sets_[id].started || id_map_[id] == kIdLocal) {
      return;
    }

    advertising_callbacks_->OnPeriodicAdvertisingEnabled(id, enable, advertising_status);
  }

  template <class View>
  void on_set_advertising_set_random_address_complete(
      AdvertiserId advertiser_id, AddressWithType address_with_type, CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto complete_view = LeSetAdvertisingSetRandomAddressCompleteView::Create(view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      log::error("Got a command complete with status {}", ErrorCodeText(complete_view.GetStatus()));
    } else {
      log::info(
          "update random address for advertising set {} : {}",
          advertiser_id,
          address_with_type.GetAddress());
      advertising_sets_[advertiser_id].current_address = address_with_type;
    }
  }

  template <class View>
  void check_status_with_id(bool send_callback, AdvertiserId id, CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto status_view = View::Create(view);
    log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
    if (status_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info(
          "Got a Command complete {}, status {}",
          OpCodeText(view.GetCommandOpCode()),
          ErrorCodeText(status_view.GetStatus()));
    }
    AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
    if (status_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info("Got a command complete with status {}", ErrorCodeText(status_view.GetStatus()));
      advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
    }

    // Do not trigger callback if the advertiser not stated yet, or the advertiser is not register
    // from Java layer
    if (advertising_callbacks_ == nullptr || !advertising_sets_[id].started || id_map_[id] == kIdLocal) {
      return;
    }

    if (com::android::bluetooth::flags::divide_long_single_gap_data()) {
      // Do not trigger callback if send_callback is false
      if (!send_callback) {
        return;
      }
    }

    OpCode opcode = view.GetCommandOpCode();

    switch (opcode) {
      case OpCode::LE_SET_ADVERTISING_PARAMETERS:
        advertising_callbacks_->OnAdvertisingParametersUpdated(id, le_physical_channel_tx_power_, advertising_status);
        break;
      case OpCode::LE_SET_ADVERTISING_DATA:
      case OpCode::LE_SET_EXTENDED_ADVERTISING_DATA:
        advertising_callbacks_->OnAdvertisingDataSet(id, advertising_status);
        break;
      case OpCode::LE_SET_SCAN_RESPONSE_DATA:
      case OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA:
        advertising_callbacks_->OnScanResponseDataSet(id, advertising_status);
        break;
      case OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS:
        advertising_callbacks_->OnPeriodicAdvertisingParametersUpdated(id, advertising_status);
        break;
      case OpCode::LE_SET_PERIODIC_ADVERTISING_DATA:
        advertising_callbacks_->OnPeriodicAdvertisingDataSet(id, advertising_status);
        break;
      case OpCode::LE_MULTI_ADVT: {
        auto command_view = LeMultiAdvtCompleteView::Create(view);
        log::assert_that(command_view.IsValid(), "assert failed: command_view.IsValid()");
        auto sub_opcode = command_view.GetSubCmd();
        switch (sub_opcode) {
          case SubOcf::SET_PARAM:
            advertising_callbacks_->OnAdvertisingParametersUpdated(
                id, le_physical_channel_tx_power_, advertising_status);
            break;
          case SubOcf::SET_DATA:
            advertising_callbacks_->OnAdvertisingDataSet(id, advertising_status);
            break;
          case SubOcf::SET_SCAN_RESP:
            advertising_callbacks_->OnScanResponseDataSet(id, advertising_status);
            break;
          default:
            log::warn("Unexpected sub event type {}", SubOcfText(command_view.GetSubCmd()));
        }
      } break;
      default:
        log::warn("Unexpected event type {}", OpCodeText(view.GetCommandOpCode()));
    }
  }

  void start_advertising_fail(int reg_id, AdvertisingCallback::AdvertisingStatus status) {
    log::assert_that(
        status != AdvertisingCallback::AdvertisingStatus::SUCCESS,
        "assert failed: status != AdvertisingCallback::AdvertisingStatus::SUCCESS");
    advertising_callbacks_->OnAdvertisingSetStarted(reg_id, kInvalidId, 0, status);
  }
};

LeAdvertisingManager::LeAdvertisingManager() {
  pimpl_ = std::make_unique<impl>(this);
}

void LeAdvertisingManager::ListDependencies(ModuleList* list) const {
  list->add<hci::HciLayer>();
  list->add<hci::Controller>();
  list->add<hci::AclManager>();
  list->add<hci::VendorSpecificEventManager>();
}

void LeAdvertisingManager::Start() {
  pimpl_->start(
      GetHandler(),
      GetDependency<hci::HciLayer>(),
      GetDependency<hci::Controller>(),
      GetDependency<AclManager>(),
      GetDependency<VendorSpecificEventManager>());
}

void LeAdvertisingManager::Stop() {
  pimpl_.reset();
}

std::string LeAdvertisingManager::ToString() const {
  return "Le Advertising Manager";
}

size_t LeAdvertisingManager::GetNumberOfAdvertisingInstances() const {
  return pimpl_->GetNumberOfAdvertisingInstances();
}

size_t LeAdvertisingManager::GetNumberOfAdvertisingInstancesInUse() const {
  return pimpl_->GetNumberOfAdvertisingInstancesInUse();
}

int LeAdvertisingManager::GetAdvertiserRegId(AdvertiserId advertiser_id) {
  return pimpl_->get_advertiser_reg_id(advertiser_id);
}

void LeAdvertisingManager::ExtendedCreateAdvertiser(
    uint8_t client_id,
    int reg_id,
    const AdvertisingConfig config,
    common::Callback<void(Address, AddressType)> scan_callback,
    common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback,
    uint16_t duration,
    uint8_t max_extended_advertising_events,
    os::Handler* handler) {
  AdvertisingApiType advertising_api_type = pimpl_->get_advertising_api_type();
  if (advertising_api_type != AdvertisingApiType::EXTENDED) {
    if (config.peer_address == Address::kEmpty) {
      if (config.advertising_type == hci::AdvertisingType::ADV_DIRECT_IND_HIGH ||
          config.advertising_type == hci::AdvertisingType::ADV_DIRECT_IND_LOW) {
        log::warn("Peer address can not be empty for directed advertising");
        CallOn(
            pimpl_.get(),
            &impl::start_advertising_fail,
            reg_id,
            AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
        return;
      }
    }
    GetHandler()->Post(common::BindOnce(
        &impl::create_advertiser,
        common::Unretained(pimpl_.get()),
        reg_id,
        config,
        scan_callback,
        set_terminated_callback,
        handler));

    return;
  };

  if (config.directed) {
    if (config.peer_address == Address::kEmpty) {
      log::info("Peer address can not be empty for directed advertising");
      CallOn(
          pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
      return;
    }
  }
  if (config.channel_map == 0) {
    log::info("At least one channel must be set in the map");
    CallOn(pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
    return;
  }
  if (!config.legacy_pdus) {
    if (config.connectable && config.scannable) {
      log::info("Extended advertising PDUs can not be connectable and scannable");
      CallOn(
          pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
      return;
    }
    if (config.high_duty_directed_connectable) {
      log::info("Extended advertising PDUs can not be high duty cycle");
      CallOn(
          pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
      return;
    }
  }
  if (config.interval_min > config.interval_max) {
    log::info(
        "Advertising interval: min ({}) > max ({})", config.interval_min, config.interval_max);
    CallOn(pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
    return;
  }
  CallOn(
      pimpl_.get(),
      &impl::create_extended_advertiser,
      client_id,
      reg_id,
      config,
      scan_callback,
      set_terminated_callback,
      duration,
      max_extended_advertising_events,
      handler);
  return;
}

void LeAdvertisingManager::StartAdvertising(
    AdvertiserId advertiser_id,
    const AdvertisingConfig config,
    uint16_t duration,
    base::OnceCallback<void(uint8_t /* status */)> status_callback,
    base::OnceCallback<void(uint8_t /* status */)> timeout_callback,
    common::Callback<void(Address, AddressType)> scan_callback,
    common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback,
    os::Handler* handler) {
  CallOn(
      pimpl_.get(),
      &impl::start_advertising,
      advertiser_id,
      config,
      duration,
      std::move(status_callback),
      std::move(timeout_callback),
      scan_callback,
      set_terminated_callback,
      handler);
}

void LeAdvertisingManager::RegisterAdvertiser(
    common::ContextualOnceCallback<void(uint8_t /* inst_id */, uint8_t /* status */)> callback) {
  CallOn(pimpl_.get(), &impl::register_advertiser, std::move(callback));
}

void LeAdvertisingManager::GetOwnAddress(uint8_t advertiser_id) {
  CallOn(pimpl_.get(), &impl::get_own_address, advertiser_id);
}

void LeAdvertisingManager::SetParameters(AdvertiserId advertiser_id, AdvertisingConfig config) {
  CallOn(pimpl_.get(), &impl::set_parameters, advertiser_id, config);
}

void LeAdvertisingManager::SetData(AdvertiserId advertiser_id, bool set_scan_rsp, std::vector<GapData> data) {
  CallOn(pimpl_.get(), &impl::set_data, advertiser_id, set_scan_rsp, data);
}

void LeAdvertisingManager::EnableAdvertiser(
    AdvertiserId advertiser_id, bool enable, uint16_t duration, uint8_t max_extended_advertising_events) {
  CallOn(pimpl_.get(), &impl::enable_advertiser, advertiser_id, enable, duration, max_extended_advertising_events);
}

void LeAdvertisingManager::SetPeriodicParameters(
    AdvertiserId advertiser_id, PeriodicAdvertisingParameters periodic_advertising_parameters) {
  CallOn(pimpl_.get(), &impl::set_periodic_parameter, advertiser_id, periodic_advertising_parameters);
}

void LeAdvertisingManager::SetPeriodicData(AdvertiserId advertiser_id, std::vector<GapData> data) {
  CallOn(pimpl_.get(), &impl::set_periodic_data, advertiser_id, data);
}

void LeAdvertisingManager::EnablePeriodicAdvertising(AdvertiserId advertiser_id, bool enable, bool include_adi) {
  CallOn(pimpl_.get(), &impl::enable_periodic_advertising, advertiser_id, enable, include_adi);
}

void LeAdvertisingManager::RemoveAdvertiser(AdvertiserId advertiser_id) {
  CallOn(pimpl_.get(), &impl::remove_advertiser, advertiser_id);
}

void LeAdvertisingManager::RegisterAdvertisingCallback(AdvertisingCallback* advertising_callback) {
  CallOn(pimpl_.get(), &impl::register_advertising_callback, advertising_callback);
}

}  // namespace hci
}  // namespace bluetooth
