/*
 * 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_scanning_manager.h"

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

#include <memory>
#include <unordered_map>

#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_periodic_sync_manager.h"
#include "hci/le_scanning_interface.h"
#include "hci/le_scanning_reassembler.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 "storage/storage_module.h"

namespace bluetooth {
namespace hci {

constexpr uint16_t kLeScanWindowMin = 0x0004;
constexpr uint16_t kLeScanWindowMax = 0x4000;
constexpr int64_t kLeScanRssiMin = -127;
constexpr int64_t kLeScanRssiMax = 20;
constexpr int64_t kLeScanRssiUnknown = 127;
constexpr int64_t kLeRxPathLossCompMin = -128;
constexpr int64_t kLeRxPathLossCompMax = 127;
constexpr uint16_t kDefaultLeExtendedScanWindow = 4800;
constexpr uint16_t kLeExtendedScanWindowMax = 0xFFFF;
constexpr uint16_t kLeScanIntervalMin = 0x0004;
constexpr uint16_t kLeScanIntervalMax = 0x4000;
constexpr uint16_t kDefaultLeExtendedScanInterval = 4800;
constexpr uint16_t kLeExtendedScanIntervalMax = 0xFFFF;

constexpr uint8_t kScannableBit = 1;
constexpr uint8_t kDirectedBit = 2;
constexpr uint8_t kScanResponseBit = 3;
constexpr uint8_t kLegacyBit = 4;
constexpr uint8_t kDataStatusBits = 5;

// system properties
const std::string kLeRxPathLossCompProperty = "bluetooth.hardware.radio.le_rx_path_loss_comp_db";

const ModuleFactory LeScanningManager::Factory = ModuleFactory([]() { return new LeScanningManager(); });

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

struct Scanner {
  Uuid app_uuid;
  bool in_use;
};

class NullScanningCallback : public ScanningCallback {
  void OnScannerRegistered(
      const Uuid /* app_uuid */, ScannerId /* scanner_id */, ScanningStatus /* status */) override {
    log::info("OnScannerRegistered in NullScanningCallback");
  }
  void OnSetScannerParameterComplete(
      ScannerId /* scanner_id */, ScanningStatus /* status */) override {
    log::info("OnSetScannerParameterComplete in NullScanningCallback");
  }
  void OnScanResult(
      uint16_t /* event_type */,
      uint8_t /* address_type */,
      Address /* address */,
      uint8_t /* primary_phy */,
      uint8_t /* secondary_phy */,
      uint8_t /* advertising_sid */,
      int8_t /* tx_power */,
      int8_t /* rssi */,
      uint16_t /* periodic_advertising_interval */,
      std::vector<uint8_t> /* advertising_data */) override {
    log::info("OnScanResult in NullScanningCallback");
  }
  void OnTrackAdvFoundLost(
      AdvertisingFilterOnFoundOnLostInfo /* on_found_on_lost_info */) override {
    log::info("OnTrackAdvFoundLost in NullScanningCallback");
  }
  void OnBatchScanReports(
      int /* client_if */,
      int /* status */,
      int /* report_format */,
      int /* num_records */,
      std::vector<uint8_t> /* data */) override {
    log::info("OnBatchScanReports in NullScanningCallback");
  }
  void OnBatchScanThresholdCrossed(int /* client_if */) override {
    log::info("OnBatchScanThresholdCrossed in NullScanningCallback");
  }
  void OnTimeout() override {
    log::info("OnTimeout in NullScanningCallback");
  }
  void OnFilterEnable(Enable /* enable */, uint8_t /* status */) override {
    log::info("OnFilterEnable in NullScanningCallback");
  }
  void OnFilterParamSetup(
      uint8_t /* available_spaces */, ApcfAction /* action */, uint8_t /* status */) override {
    log::info("OnFilterParamSetup in NullScanningCallback");
  }
  void OnFilterConfigCallback(
      ApcfFilterType /* filter_type */,
      uint8_t /* available_spaces */,
      ApcfAction /* action */,
      uint8_t /* status */) override {
    log::info("OnFilterConfigCallback in NullScanningCallback");
  }
  void OnPeriodicSyncStarted(
      int /* reg_id */,
      uint8_t /* status */,
      uint16_t /* sync_handle */,
      uint8_t /* advertising_sid */,
      AddressWithType /* address_with_type */,
      uint8_t /* phy */,
      uint16_t /* interval */) override {
    log::info("OnPeriodicSyncStarted in NullScanningCallback");
  };
  void OnPeriodicSyncReport(
      uint16_t /* sync_handle */,
      int8_t /* tx_power */,
      int8_t /* rssi */,
      uint8_t /* status */,
      std::vector<uint8_t> /* data */) override {
    log::info("OnPeriodicSyncReport in NullScanningCallback");
  };
  void OnPeriodicSyncLost(uint16_t /* sync_handle */) override {
    log::info("OnPeriodicSyncLost in NullScanningCallback");
  };
  void OnPeriodicSyncTransferred(
      int /* pa_source */, uint8_t /* status */, Address /* address */) override {
    log::info("OnPeriodicSyncTransferred in NullScanningCallback");
  };
  void OnBigInfoReport(uint16_t /* sync_handle */, bool /* encrypted */) {
    log::info("OnBigInfoReport in NullScanningCallback");
  };
};

enum class BatchScanState {
  ERROR_STATE = 0,
  ENABLE_CALLED = 1,
  ENABLED_STATE = 2,
  DISABLE_CALLED = 3,
  DISABLED_STATE = 4,
};

#define BTM_BLE_BATCH_SCAN_MODE_DISABLE 0
#define BTM_BLE_BATCH_SCAN_MODE_PASS 1
#define BTM_BLE_BATCH_SCAN_MODE_ACTI 2
#define BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI 3

struct BatchScanConfig {
  BatchScanState current_state;
  BatchScanMode scan_mode;
  uint32_t scan_interval;
  uint32_t scan_window;
  BatchScanDiscardRule discard_rule;
  ScannerId ref_value;
};

struct LeScanningManager::impl : public LeAddressManagerCallback {
  impl(Module* module) : module_(module), le_scanning_interface_(nullptr) {}

  ~impl() {
    if (address_manager_registered_) {
      le_address_manager_->Unregister(this);
    }
  }

  void start(
      os::Handler* handler,
      HciLayer* hci_layer,
      Controller* controller,
      AclManager* acl_manager,
      VendorSpecificEventManager* vendor_specific_event_manager,
      storage::StorageModule* storage_module) {
    module_handler_ = handler;
    hci_layer_ = hci_layer;
    controller_ = controller;
    acl_manager_ = acl_manager;
    vendor_specific_event_manager_ = vendor_specific_event_manager;
    storage_module_ = storage_module;
    le_address_manager_ = acl_manager->GetLeAddressManager();
    le_scanning_interface_ = hci_layer_->GetLeScanningInterface(
        module_handler_->BindOn(this, &LeScanningManager::impl::handle_scan_results));
    periodic_sync_manager_.Init(le_scanning_interface_, module_handler_);
    /* Check to see if the opcode is supported and C19 (support for extended advertising). */
    if (controller_->IsSupported(OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS) &&
        controller->SupportsBleExtendedAdvertising()) {
      api_type_ = ScanApiType::EXTENDED;
      interval_ms_ = kDefaultLeExtendedScanInterval;
      window_ms_ = kDefaultLeExtendedScanWindow;
      phy_ = static_cast<uint8_t>(PhyType::LE_1M);
    } else if (controller_->IsSupported(OpCode::LE_EXTENDED_SCAN_PARAMS)) {
      api_type_ = ScanApiType::ANDROID_HCI;
    } else {
      api_type_ = ScanApiType::LEGACY;
    }
    is_filter_supported_ = controller_->IsSupported(OpCode::LE_ADV_FILTER);
    if (is_filter_supported_) {
      le_scanning_interface_->EnqueueCommand(
          LeAdvFilterReadExtendedFeaturesBuilder::Create(),
          module_handler_->BindOnceOn(this, &impl::on_apcf_read_extended_features_complete));
    }
    is_batch_scan_supported_ = controller->IsSupported(OpCode::LE_BATCH_SCAN);
    is_periodic_advertising_sync_transfer_sender_supported_ =
        controller_->SupportsBlePeriodicAdvertisingSyncTransferSender();
    total_num_of_advt_tracked_ = controller->GetVendorCapabilities().total_num_of_advt_tracked_;
    if (is_batch_scan_supported_) {
      vendor_specific_event_manager_->RegisterEventHandler(
          VseSubeventCode::BLE_THRESHOLD, handler->BindOn(this, &LeScanningManager::impl::on_storage_threshold_breach));
      vendor_specific_event_manager_->RegisterEventHandler(
          VseSubeventCode::BLE_TRACKING, handler->BindOn(this, &LeScanningManager::impl::on_advertisement_tracking));
    }
    scanners_ = std::vector<Scanner>(kMaxAppNum + 1);
    for (size_t i = 0; i < scanners_.size(); i++) {
      scanners_[i].app_uuid = Uuid::kEmpty;
      scanners_[i].in_use = false;
    }
    batch_scan_config_.current_state = BatchScanState::DISABLED_STATE;
    batch_scan_config_.ref_value = kInvalidScannerId;
    le_rx_path_loss_comp_ = get_rx_path_loss_compensation();
  }

  void stop() {
    for (auto subevent_code : LeScanningEvents) {
      hci_layer_->UnregisterLeEventHandler(subevent_code);
    }
    if (is_batch_scan_supported_) {
      // TODO implete vse module
      // hci_layer_->UnregisterVesEventHandler(VseSubeventCode::BLE_THRESHOLD);
      // hci_layer_->UnregisterVesEventHandler(VseSubeventCode::BLE_TRACKING);
    }
    batch_scan_config_.current_state = BatchScanState::DISABLED_STATE;
    batch_scan_config_.ref_value = kInvalidScannerId;
    scanning_callbacks_ = &null_scanning_callback_;
    periodic_sync_manager_.SetScanningCallback(scanning_callbacks_);
  }

  void handle_scan_results(LeMetaEventView event) {
    switch (event.GetSubeventCode()) {
      case SubeventCode::ADVERTISING_REPORT:
        handle_advertising_report(LeAdvertisingReportRawView::Create(event));
        break;
      case SubeventCode::DIRECTED_ADVERTISING_REPORT:
        handle_directed_advertising_report(LeDirectedAdvertisingReportView::Create(event));
        break;
      case SubeventCode::EXTENDED_ADVERTISING_REPORT:
        handle_extended_advertising_report(LeExtendedAdvertisingReportRawView::Create(event));
        break;
      case SubeventCode::PERIODIC_ADVERTISING_SYNC_ESTABLISHED:
        LePeriodicAdvertisingSyncEstablishedView::Create(event);
        periodic_sync_manager_.HandleLePeriodicAdvertisingSyncEstablished(
            LePeriodicAdvertisingSyncEstablishedView::Create(event));
        break;
      case SubeventCode::PERIODIC_ADVERTISING_REPORT:
        periodic_sync_manager_.HandleLePeriodicAdvertisingReport(LePeriodicAdvertisingReportView::Create(event));
        break;
      case SubeventCode::PERIODIC_ADVERTISING_SYNC_LOST:
        periodic_sync_manager_.HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView::Create(event));
        break;
      case SubeventCode::PERIODIC_ADVERTISING_SYNC_TRANSFER_RECEIVED:
        periodic_sync_manager_.HandleLePeriodicAdvertisingSyncTransferReceived(
            LePeriodicAdvertisingSyncTransferReceivedView::Create(event));
        break;
      case SubeventCode::SCAN_TIMEOUT:
        scanning_callbacks_->OnTimeout();
        break;
      case SubeventCode::BIG_INFO_ADVERTISING_REPORT:
        periodic_sync_manager_.HandleLeBigInfoAdvertisingReport(
            LeBigInfoAdvertisingReportView::Create(event));
        break;
      default:
        log::fatal("Unknown advertising subevent {}", SubeventCodeText(event.GetSubeventCode()));
    }
  }

  struct ExtendedEventTypeOptions {
    bool connectable{false};
    bool scannable{false};
    bool directed{false};
    bool scan_response{false};
    bool legacy{false};
    bool continuing{false};
    bool truncated{false};
  };

  int8_t get_rx_path_loss_compensation() {
    int8_t compensation = 0;
    auto compensation_prop = os::GetSystemProperty(kLeRxPathLossCompProperty);
    if (compensation_prop) {
      auto compensation_number = common::Int64FromString(compensation_prop.value());
      if (compensation_number) {
        int64_t number = compensation_number.value();
        if (number < kLeRxPathLossCompMin || number > kLeRxPathLossCompMax) {
          log::error("Invalid number for rx path loss compensation: {}", number);
        } else {
          compensation = number;
        }
      }
    }
    log::info("Rx path loss compensation: {}", compensation);
    return compensation;
  }

  int8_t get_rssi_after_calibration(int8_t rssi) {
    if (le_rx_path_loss_comp_ == 0 || rssi == kLeScanRssiUnknown) {
      return rssi;
    }
    int8_t calibrated_rssi = rssi;
    int64_t number = rssi + le_rx_path_loss_comp_;
    if (number < kLeScanRssiMin || number > kLeScanRssiMax) {
      log::error("Invalid number for calibrated rssi: {}", number);
    } else {
      calibrated_rssi = number;
    }
    return calibrated_rssi;
  }

  uint16_t transform_to_extended_event_type(ExtendedEventTypeOptions o) {
    return (o.connectable ? 0x0001 << 0 : 0) | (o.scannable ? 0x0001 << 1 : 0) |
           (o.directed ? 0x0001 << 2 : 0) | (o.scan_response ? 0x0001 << 3 : 0) |
           (o.legacy ? 0x0001 << 4 : 0) | (o.continuing ? 0x0001 << 5 : 0) |
           (o.truncated ? 0x0001 << 6 : 0);
  }

  void handle_advertising_report(LeAdvertisingReportRawView event_view) {
    if (!event_view.IsValid()) {
      log::info("Dropping invalid advertising event");
      return;
    }
    std::vector<LeAdvertisingResponseRaw> reports = event_view.GetResponses();
    if (reports.empty()) {
      log::info("Zero results in advertising event");
      return;
    }

    for (LeAdvertisingResponseRaw report : reports) {
      uint16_t extended_event_type = 0;
      switch (report.event_type_) {
        case AdvertisingEventType::ADV_IND:
          extended_event_type = transform_to_extended_event_type(
              {.connectable = true, .scannable = true, .legacy = true});
          break;
        case AdvertisingEventType::ADV_DIRECT_IND:
          extended_event_type = transform_to_extended_event_type(
              {.connectable = true, .directed = true, .legacy = true});
          break;
        case AdvertisingEventType::ADV_SCAN_IND:
          extended_event_type =
              transform_to_extended_event_type({.scannable = true, .legacy = true});
          break;
        case AdvertisingEventType::ADV_NONCONN_IND:
          extended_event_type = transform_to_extended_event_type({.legacy = true});
          break;
        case AdvertisingEventType::SCAN_RESPONSE:
          if (com::android::bluetooth::flags::fix_nonconnectable_scannable_advertisement()) {
            // We don't know if the initial advertising report was connectable or not.
            // LeScanningReassembler fixes the connectable field.
            extended_event_type = transform_to_extended_event_type(
                {.scannable = true, .scan_response = true, .legacy = true});
          } else {
            extended_event_type = transform_to_extended_event_type(
                {.connectable = true, .scannable = true, .scan_response = true, .legacy = true});
          }
          break;
        default:
          log::warn("Unsupported event type:{}", (uint16_t)report.event_type_);
          return;
      }

      process_advertising_package_content(
          extended_event_type,
          (uint8_t)report.address_type_,
          report.address_,
          (uint8_t)PrimaryPhyType::LE_1M,
          (uint8_t)SecondaryPhyType::NO_PACKETS,
          kAdvertisingDataInfoNotPresent,
          kTxPowerInformationNotPresent,
          report.rssi_,
          kNotPeriodicAdvertisement,
          report.advertising_data_);
    }
  }

  void handle_directed_advertising_report(LeDirectedAdvertisingReportView /*event_view*/) {
    log::warn("HCI Directed Advertising Report events are not supported");
  }

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

    std::vector<LeExtendedAdvertisingResponseRaw> reports = event_view.GetResponses();
    if (reports.empty()) {
      log::info("Zero results in advertising event");
      return;
    }

    for (LeExtendedAdvertisingResponseRaw& report : reports) {
      uint16_t event_type = report.connectable_ | (report.scannable_ << kScannableBit) |
                            (report.directed_ << kDirectedBit) | (report.scan_response_ << kScanResponseBit) |
                            (report.legacy_ << kLegacyBit) | ((uint16_t)report.data_status_ << kDataStatusBits);
      process_advertising_package_content(
          event_type,
          (uint8_t)report.address_type_,
          report.address_,
          (uint8_t)report.primary_phy_,
          (uint8_t)report.secondary_phy_,
          report.advertising_sid_,
          report.tx_power_,
          report.rssi_,
          report.periodic_advertising_interval_,
          report.advertising_data_);
    }
  }

  void process_advertising_package_content(
      uint16_t event_type,
      uint8_t address_type,
      Address address,
      uint8_t primary_phy,
      uint8_t secondary_phy,
      uint8_t advertising_sid,
      int8_t tx_power,
      int8_t rssi,
      uint16_t periodic_advertising_interval,
      const std::vector<uint8_t>& advertising_data) {
    // When using the vendor command Le Set Extended Params to
    // configure a filter accept list based e.g. on the service UUIDs
    // found in the report, we ignore the scan responses as we cannot be
    // certain that they will not be dropped by the filter.
    // TODO(b/275754998): Improve the decision on what to do with scan responses: Only when used
    // with hardware-filtering features should we ignore waiting for scan response, and make sure
    // scan responses are still reported too.
    scanning_reassembler_.SetIgnoreScanResponses(
        le_scan_type_ == LeScanType::PASSIVE ||
        filter_policy_ == LeScanningFilterPolicy::FILTER_ACCEPT_LIST_ONLY);

    std::optional<LeScanningReassembler::CompleteAdvertisingData> processed_report =
        scanning_reassembler_.ProcessAdvertisingReport(
            event_type, address_type, address, advertising_sid, advertising_data);

    if (processed_report.has_value()) {
      switch (address_type) {
        case (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS:
        case (uint8_t)AddressType::PUBLIC_IDENTITY_ADDRESS:
          address_type = (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS;
          break;
        case (uint8_t)AddressType::RANDOM_DEVICE_ADDRESS:
        case (uint8_t)AddressType::RANDOM_IDENTITY_ADDRESS:
          address_type = (uint8_t)AddressType::RANDOM_DEVICE_ADDRESS;
          break;
      }

      const uint16_t result_event_type =
          com::android::bluetooth::flags::fix_nonconnectable_scannable_advertisement()
              ? processed_report->extended_event_type
              : event_type;

      scanning_callbacks_->OnScanResult(
          result_event_type,
          address_type,
          address,
          primary_phy,
          secondary_phy,
          advertising_sid,
          tx_power,
          get_rssi_after_calibration(rssi),
          periodic_advertising_interval,
          std::move(processed_report->data));
    }
  }

  void configure_scan() {
    std::vector<PhyScanParameters> parameter_vector;
    for (int i = 0; i < 7; i++) {
      if ((phy_ & 1 << i) != 0) {
        PhyScanParameters phy_scan_parameters;
        phy_scan_parameters.le_scan_window_ = window_ms_;
        phy_scan_parameters.le_scan_interval_ = interval_ms_;
        phy_scan_parameters.le_scan_type_ = le_scan_type_;
        parameter_vector.push_back(phy_scan_parameters);
      }
    }
    uint8_t phys_in_use = phy_;

    // The Host shall not issue set scan parameter command when scanning is enabled
    stop_scan();

    if (le_address_manager_->GetAddressPolicy() != LeAddressManager::USE_PUBLIC_ADDRESS) {
      own_address_type_ = OwnAddressType::RANDOM_DEVICE_ADDRESS;
    } else {
      own_address_type_ = OwnAddressType::PUBLIC_DEVICE_ADDRESS;
    }

    switch (api_type_) {
      case ScanApiType::EXTENDED:
        le_scanning_interface_->EnqueueCommand(
            LeSetExtendedScanParametersBuilder::Create(
                own_address_type_, filter_policy_, phys_in_use, parameter_vector),
            module_handler_->BindOnceOn(this, &impl::on_set_scan_parameter_complete));
        break;
      case ScanApiType::ANDROID_HCI:
        le_scanning_interface_->EnqueueCommand(
            LeExtendedScanParamsBuilder::Create(
                le_scan_type_, interval_ms_, window_ms_, own_address_type_, filter_policy_),
            module_handler_->BindOnceOn(this, &impl::on_set_scan_parameter_complete));

        break;
      case ScanApiType::LEGACY:
        le_scanning_interface_->EnqueueCommand(

            LeSetScanParametersBuilder::Create(
                le_scan_type_, interval_ms_, window_ms_, own_address_type_, filter_policy_),
            module_handler_->BindOnceOn(this, &impl::on_set_scan_parameter_complete));
        break;
    }
  }

  void register_scanner(const Uuid app_uuid) {
    for (uint8_t i = 1; i <= kMaxAppNum; i++) {
      if (scanners_[i].in_use && scanners_[i].app_uuid == app_uuid) {
        log::error("Application already registered {}", app_uuid.ToString());
        scanning_callbacks_->OnScannerRegistered(app_uuid, 0x00, ScanningCallback::ScanningStatus::INTERNAL_ERROR);
        return;
      }
    }

    // valid value of scanner id : 1 ~ kMaxAppNum
    for (uint8_t i = 1; i <= kMaxAppNum; i++) {
      if (!scanners_[i].in_use) {
        scanners_[i].app_uuid = app_uuid;
        scanners_[i].in_use = true;
        scanning_callbacks_->OnScannerRegistered(app_uuid, i, ScanningCallback::ScanningStatus::SUCCESS);
        return;
      }
    }

    log::error("Unable to register scanner, max client reached:{}", kMaxAppNum);
    scanning_callbacks_->OnScannerRegistered(app_uuid, 0x00, ScanningCallback::ScanningStatus::NO_RESOURCES);
  }

  void unregister_scanner(ScannerId scanner_id) {
    if (scanner_id <= 0 || scanner_id > kMaxAppNum) {
      log::warn("Invalid scanner id");
      return;
    }

    if (scanners_[scanner_id].in_use) {
      scanners_[scanner_id].in_use = false;
      scanners_[scanner_id].app_uuid = Uuid::kEmpty;
    } else {
      log::warn("Unregister scanner with unused scanner id");
    }
  }

  void scan(bool start) {
    // On-resume flag should always be reset if there is an explicit start/stop call.
    scan_on_resume_ = false;
    if (start) {
      configure_scan();
      start_scan();
    } else {
      if (address_manager_registered_) {
        le_address_manager_->Unregister(this);
        address_manager_registered_ = false;
        paused_ = false;
      }
      stop_scan();
    }
  }

  void start_scan() {
    // If we receive start_scan during paused, set scan_on_resume_ to true
    if (paused_ && address_manager_registered_) {
      scan_on_resume_ = true;
      return;
    }
    is_scanning_ = true;
    if (!address_manager_registered_) {
      le_address_manager_->Register(this);
      address_manager_registered_ = true;
    }

    switch (api_type_) {
      case ScanApiType::EXTENDED:
        le_scanning_interface_->EnqueueCommand(
            LeSetExtendedScanEnableBuilder::Create(
                Enable::ENABLED,
#if TARGET_FLOSS
                FilterDuplicates::ENABLED /* filter duplicates */,
#else
                FilterDuplicates::DISABLED /* filter duplicates */,
#endif
                0,
                0),
            module_handler_->BindOnce(check_complete<LeSetExtendedScanEnableCompleteView>));
        break;
      case ScanApiType::ANDROID_HCI:
      case ScanApiType::LEGACY:
        le_scanning_interface_->EnqueueCommand(
            LeSetScanEnableBuilder::Create(
                Enable::ENABLED, Enable::DISABLED /* filter duplicates */),
            module_handler_->BindOnce(check_complete<LeSetScanEnableCompleteView>));
        break;
    }
  }

  void stop_scan() {
    if (!is_scanning_) {
      log::info("Scanning already stopped, return!");
      return;
    }
    is_scanning_ = false;

    switch (api_type_) {
      case ScanApiType::EXTENDED:
        le_scanning_interface_->EnqueueCommand(
            LeSetExtendedScanEnableBuilder::Create(
                Enable::DISABLED,
#if TARGET_FLOSS
                FilterDuplicates::ENABLED /* filter duplicates */,
#else
                FilterDuplicates::DISABLED /* filter duplicates */,
#endif
                0,
                0),
            module_handler_->BindOnce(check_complete<LeSetExtendedScanEnableCompleteView>));
        break;
      case ScanApiType::ANDROID_HCI:
      case ScanApiType::LEGACY:
        le_scanning_interface_->EnqueueCommand(
            LeSetScanEnableBuilder::Create(
                Enable::DISABLED, Enable::DISABLED /* filter duplicates */),
            module_handler_->BindOnce(check_complete<LeSetScanEnableCompleteView>));
        break;
    }
  }

  void set_scan_parameters(
      ScannerId scanner_id,
      LeScanType scan_type,
      uint16_t scan_interval,
      uint16_t scan_window,
      uint8_t scan_phy) {
    uint32_t max_scan_interval = kLeScanIntervalMax;
    uint32_t max_scan_window = kLeScanWindowMax;
    if (api_type_ == ScanApiType::EXTENDED) {
      max_scan_interval = kLeExtendedScanIntervalMax;
      max_scan_window = kLeExtendedScanWindowMax;
    }

    if (scan_type != LeScanType::ACTIVE && scan_type != LeScanType::PASSIVE) {
      log::error("Invalid scan type");
      scanning_callbacks_->OnSetScannerParameterComplete(
          scanner_id, ScanningCallback::ScanningStatus::ILLEGAL_PARAMETER);
      return;
    }
    if (scan_interval > max_scan_interval || scan_interval < kLeScanIntervalMin) {
      log::error("Invalid scan_interval {}", scan_interval);
      scanning_callbacks_->OnSetScannerParameterComplete(
          scanner_id, ScanningCallback::ScanningStatus::ILLEGAL_PARAMETER);
      return;
    }
    if (scan_window > max_scan_window || scan_window < kLeScanWindowMin) {
      log::error("Invalid scan_window {}", scan_window);
      scanning_callbacks_->OnSetScannerParameterComplete(
          scanner_id, ScanningCallback::ScanningStatus::ILLEGAL_PARAMETER);
      return;
    }
    le_scan_type_ = scan_type;
    interval_ms_ = scan_interval;
    window_ms_ = scan_window;
    if (com::android::bluetooth::flags::phy_to_native()) phy_ = scan_phy;
    scanning_callbacks_->OnSetScannerParameterComplete(scanner_id, ScanningCallback::SUCCESS);
  }

  void set_scan_filter_policy(LeScanningFilterPolicy filter_policy) {
    filter_policy_ = filter_policy;
  }

  void scan_filter_enable(bool enable) {
    if (!is_filter_supported_) {
      log::warn("Advertising filter is not supported");
      return;
    }

    Enable apcf_enable = enable ? Enable::ENABLED : Enable::DISABLED;
    le_scanning_interface_->EnqueueCommand(
        LeAdvFilterEnableBuilder::Create(apcf_enable),
        module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
  }

  bool is_bonded(Address target_address) {
    for (auto device : storage_module_->GetBondedDevices()) {
      if (device.GetAddress() == target_address) {
        log::debug("Addresses match!");
        return true;
      }
    }
    log::debug("Addresse DON'Ts match!");
    return false;
  }

  void scan_filter_parameter_setup(
      ApcfAction action, uint8_t filter_index, AdvertisingFilterParameter advertising_filter_parameter) {
    if (!is_filter_supported_) {
      log::warn("Advertising filter is not supported");
      return;
    }

    auto entry = remove_me_later_map_.find(filter_index);
    switch (action) {
      case ApcfAction::ADD:
        le_scanning_interface_->EnqueueCommand(
            LeAdvFilterAddFilteringParametersBuilder::Create(
                filter_index,
                advertising_filter_parameter.feature_selection,
                advertising_filter_parameter.list_logic_type,
                advertising_filter_parameter.filter_logic_type,
                advertising_filter_parameter.rssi_high_thresh,
                advertising_filter_parameter.delivery_mode,
                advertising_filter_parameter.onfound_timeout,
                advertising_filter_parameter.onfound_timeout_cnt,
                advertising_filter_parameter.rssi_low_thresh,
                advertising_filter_parameter.onlost_timeout,
                advertising_filter_parameter.num_of_tracking_entries),
            module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
        break;
      case ApcfAction::DELETE:
        tracker_id_map_.erase(filter_index);
        le_scanning_interface_->EnqueueCommand(
            LeAdvFilterDeleteFilteringParametersBuilder::Create(filter_index),
            module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));

        // IRK Scanning
        if (entry != remove_me_later_map_.end()) {
          // Don't want to remove for a bonded device
          if (!is_bonded(entry->second.GetAddress())) {
            le_address_manager_->RemoveDeviceFromResolvingList(
                static_cast<PeerAddressType>(entry->second.GetAddressType()), entry->second.GetAddress());
          }
          remove_me_later_map_.erase(filter_index);
        }

        break;
      case ApcfAction::CLEAR:
        le_scanning_interface_->EnqueueCommand(
            LeAdvFilterClearFilteringParametersBuilder::Create(),
            module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));

        // IRK Scanning
        if (entry != remove_me_later_map_.end()) {
          // Don't want to remove for a bonded device
          if (!is_bonded(entry->second.GetAddress())) {
            le_address_manager_->RemoveDeviceFromResolvingList(
                static_cast<PeerAddressType>(entry->second.GetAddressType()), entry->second.GetAddress());
          }
          remove_me_later_map_.erase(filter_index);
        }

        break;
      default:
        log::error("Unknown action type: {}", (uint16_t)action);
        break;
    }
  }

  void scan_filter_add(uint8_t filter_index, std::vector<AdvertisingPacketContentFilterCommand> filters) {
    if (!is_filter_supported_) {
      log::warn("Advertising filter is not supported");
      return;
    }

    ApcfAction apcf_action = ApcfAction::ADD;
    for (auto filter : filters) {
      /* If data is passed, both mask and data have to be the same length */
      if (filter.data.size() != filter.data_mask.size() && filter.data.size() != 0 && filter.data_mask.size() != 0) {
        log::error("data and data_mask are of different size");
        continue;
      }

      switch (filter.filter_type) {
        case ApcfFilterType::BROADCASTER_ADDRESS: {
          update_address_filter(apcf_action, filter_index, filter.address, filter.application_address_type, filter.irk);
          break;
        }
        case ApcfFilterType::SERVICE_UUID:
        case ApcfFilterType::SERVICE_SOLICITATION_UUID: {
          update_uuid_filter(apcf_action, filter_index, filter.filter_type, filter.uuid, filter.uuid_mask);
          break;
        }
        case ApcfFilterType::LOCAL_NAME: {
          update_local_name_filter(apcf_action, filter_index, filter.name);
          break;
        }
        case ApcfFilterType::MANUFACTURER_DATA: {
          update_manufacturer_data_filter(
              apcf_action, filter_index, filter.company, filter.company_mask, filter.data, filter.data_mask);
          break;
        }
        case ApcfFilterType::SERVICE_DATA: {
          update_service_data_filter(apcf_action, filter_index, filter.data, filter.data_mask);
          break;
        }
        case ApcfFilterType::TRANSPORT_DISCOVERY_DATA: {
          update_transport_discovery_data_filter(
              apcf_action,
              filter_index,
              filter.org_id,
              filter.tds_flags,
              filter.tds_flags_mask,
              filter.data,
              filter.data_mask,
              filter.meta_data_type,
              filter.meta_data);
          break;
        }
        case ApcfFilterType::AD_TYPE: {
          update_ad_type_filter(apcf_action, filter_index, filter.ad_type, filter.data, filter.data_mask);
          break;
        }
        default:
          log::error("Unknown filter type: {}", (uint16_t)filter.filter_type);
          break;
      }
    }
  }

  std::unordered_map<uint8_t, AddressWithType> remove_me_later_map_;

  void update_address_filter(
      ApcfAction action,
      uint8_t filter_index,
      Address address,
      ApcfApplicationAddressType address_type,
      std::array<uint8_t, 16> irk) {
    if (action != ApcfAction::CLEAR) {
      /*
       * The vendor command (APCF Filtering 0x0157) takes Public (0) or Random (1)
       * or Addresses type not applicable (2).
       *
       * Advertising results have four types:
       * ￼    -  Public = 0
       * ￼    -  Random = 1
       * ￼    -  Public ID = 2
       * ￼    -  Random ID = 3
       *
       * e.g. specifying PUBLIC (0) will only return results with a public
       * address. It will ignore resolved addresses, since they return PUBLIC
       * IDENTITY (2). For this, Addresses type not applicable (0x02) must be specified.
       * This should also cover if the RPA is derived from RANDOM STATIC.
       */
      le_scanning_interface_->EnqueueCommand(
          LeAdvFilterBroadcasterAddressBuilder::Create(
              action, filter_index, address, ApcfApplicationAddressType::NOT_APPLICABLE),
          module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
      if (!is_empty_128bit(irk)) {
        // If an entry exists for this filter index, replace data because the filter has been
        // updated.
        auto entry = remove_me_later_map_.find(filter_index);
        // IRK Scanning
        if (entry != remove_me_later_map_.end()) {
          // Don't want to remove for a bonded device
          if (!is_bonded(entry->second.GetAddress())) {
            le_address_manager_->RemoveDeviceFromResolvingList(
                static_cast<PeerAddressType>(entry->second.GetAddressType()), entry->second.GetAddress());
          }
          remove_me_later_map_.erase(filter_index);
        }

        // Now replace it with a new one
        std::array<uint8_t, 16> empty_irk;
        le_address_manager_->AddDeviceToResolvingList(
            static_cast<PeerAddressType>(address_type), address, irk, empty_irk);
        remove_me_later_map_.emplace(filter_index, AddressWithType(address, static_cast<AddressType>(address_type)));
      }
    } else {
      le_scanning_interface_->EnqueueCommand(
          LeAdvFilterClearBroadcasterAddressBuilder::Create(filter_index),
          module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
      auto entry = remove_me_later_map_.find(filter_index);
      if (entry != remove_me_later_map_.end()) {
        // TODO(optedoblivion): If not bonded
        le_address_manager_->RemoveDeviceFromResolvingList(static_cast<PeerAddressType>(address_type), address);
        remove_me_later_map_.erase(filter_index);
      }
    }
  }

  bool is_empty_128bit(const std::array<uint8_t, 16> data) {
    for (int i = 0; i < 16; i++) {
      if (data[i] != (uint8_t)0) {
        return false;
      }
    }
    return true;
  }

  void update_uuid_filter(
      ApcfAction action, uint8_t filter_index, ApcfFilterType filter_type, Uuid uuid, Uuid uuid_mask) {
    std::vector<uint8_t> combined_data = {};
    if (action != ApcfAction::CLEAR) {
      uint8_t uuid_len = uuid.GetShortestRepresentationSize();
      if (uuid_len == Uuid::kNumBytes16) {
        uint16_t data = uuid.As16Bit();
        combined_data.push_back((uint8_t)data);
        combined_data.push_back((uint8_t)(data >> 8));
      } else if (uuid_len == Uuid::kNumBytes32) {
        uint32_t data = uuid.As32Bit();
        combined_data.push_back((uint8_t)data);
        combined_data.push_back((uint8_t)(data >> 8));
        combined_data.push_back((uint8_t)(data >> 16));
        combined_data.push_back((uint8_t)(data >> 24));
      } else if (uuid_len == Uuid::kNumBytes128) {
        auto data = uuid.To128BitLE();
        combined_data.insert(combined_data.end(), data.begin(), data.end());
      } else {
        log::error("illegal UUID length: {}", (uint16_t)uuid_len);
        return;
      }

      if (!uuid_mask.IsEmpty()) {
        if (uuid_len == Uuid::kNumBytes16) {
          uint16_t data = uuid_mask.As16Bit();
          combined_data.push_back((uint8_t)data);
          combined_data.push_back((uint8_t)(data >> 8));
        } else if (uuid_len == Uuid::kNumBytes32) {
          uint32_t data = uuid_mask.As32Bit();
          combined_data.push_back((uint8_t)data);
          combined_data.push_back((uint8_t)(data >> 8));
          combined_data.push_back((uint8_t)(data >> 16));
          combined_data.push_back((uint8_t)(data >> 24));
        } else if (uuid_len == Uuid::kNumBytes128) {
          auto data = uuid_mask.To128BitLE();
          combined_data.insert(combined_data.end(), data.begin(), data.end());
        }
      } else {
        std::vector<uint8_t> data(uuid_len, 0xFF);
        combined_data.insert(combined_data.end(), data.begin(), data.end());
      }
    }

    if (filter_type == ApcfFilterType::SERVICE_UUID) {
      le_scanning_interface_->EnqueueCommand(
          LeAdvFilterServiceUuidBuilder::Create(action, filter_index, combined_data),
          module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
    } else {
      le_scanning_interface_->EnqueueCommand(
          LeAdvFilterSolicitationUuidBuilder::Create(action, filter_index, combined_data),
          module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
    }
  }

  void update_local_name_filter(ApcfAction action, uint8_t filter_index, std::vector<uint8_t> name) {
    le_scanning_interface_->EnqueueCommand(
        LeAdvFilterLocalNameBuilder::Create(action, filter_index, name),
        module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
  }

  void update_manufacturer_data_filter(
      ApcfAction action,
      uint8_t filter_index,
      uint16_t company_id,
      uint16_t company_id_mask,
      std::vector<uint8_t> data,
      std::vector<uint8_t> data_mask) {
    if (data.size() != data_mask.size()) {
      log::error("manufacturer data mask should have the same length as manufacturer data");
      return;
    }
    std::vector<uint8_t> combined_data = {};
    if (action != ApcfAction::CLEAR) {
      combined_data.push_back((uint8_t)company_id);
      combined_data.push_back((uint8_t)(company_id >> 8));
      if (data.size() != 0) {
        combined_data.insert(combined_data.end(), data.begin(), data.end());
      }
      if (company_id_mask != 0) {
        combined_data.push_back((uint8_t)company_id_mask);
        combined_data.push_back((uint8_t)(company_id_mask >> 8));
      } else {
        combined_data.push_back(0xFF);
        combined_data.push_back(0xFF);
      }
      if (data_mask.size() != 0) {
        combined_data.insert(combined_data.end(), data_mask.begin(), data_mask.end());
      }
    }

    le_scanning_interface_->EnqueueCommand(
        LeAdvFilterManufacturerDataBuilder::Create(action, filter_index, combined_data),
        module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
  }

  void update_service_data_filter(
      ApcfAction action, uint8_t filter_index, std::vector<uint8_t> data, std::vector<uint8_t> data_mask) {
    if (data.size() != data_mask.size()) {
      log::error("service data mask should have the same length as service data");
      return;
    }
    std::vector<uint8_t> combined_data = {};
    if (action != ApcfAction::CLEAR && data.size() != 0) {
      combined_data.insert(combined_data.end(), data.begin(), data.end());
      combined_data.insert(combined_data.end(), data_mask.begin(), data_mask.end());
    }

    le_scanning_interface_->EnqueueCommand(
        LeAdvFilterServiceDataBuilder::Create(action, filter_index, combined_data),
        module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
  }

  void update_transport_discovery_data_filter(
      ApcfAction action,
      uint8_t filter_index,
      uint8_t org_id,
      uint8_t tds_flags,
      uint8_t tds_flags_mask,
      std::vector<uint8_t> transport_data,
      std::vector<uint8_t> transport_data_mask,
      ApcfMetaDataType meta_data_type,
      std::vector<uint8_t> meta_data) {
    LocalVersionInformation local_version_information = controller_->GetLocalVersionInformation();

    // In QTI controller, transport discovery data filter are supported by default. Check is added
    // to keep backward compatibility.
    if (!is_transport_discovery_data_filter_supported_ &&
        !(local_version_information.manufacturer_name_ == LMP_COMPID_QTI)) {
      log::warn("transport discovery data filter isn't supported");
      return;
    }

    log::info(
        "org id: {}, tds_flags: {}, tds_flags_mask: {}, transport_data size: {}, "
        "transport_data_mask size: {}, meta_data_type: {}, meta_data size: {}",
        org_id,
        tds_flags,
        tds_flags_mask,
        transport_data.size(),
        transport_data_mask.size(),
        (uint8_t)meta_data_type,
        meta_data.size());

    // 0x02 Wi-Fi Alliance Neighbor Awareness Networking & meta_data_type is 0x01 for NAN Hash.
    if (org_id == 0x02) {
      // meta data contains WIFI NAN hash, reverse it before sending controller.
      switch (meta_data_type) {
        case ApcfMetaDataType::WIFI_NAN_HASH:
          std::reverse(meta_data.begin(), meta_data.end());
          break;
        default:
          break;
      }
    }

    if (is_transport_discovery_data_filter_supported_) {
      le_scanning_interface_->EnqueueCommand(
          LeAdvFilterTransportDiscoveryDataBuilder::Create(
              action,
              filter_index,
              org_id,
              tds_flags,
              tds_flags_mask,
              transport_data,
              transport_data_mask,
              meta_data_type,
              meta_data),
          module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
    } else {
      // In QTI controller, transport discovery data filter are supported by default.
      // keeping old version for backward compatibility
      std::vector<uint8_t> combined_data = {};
      if (action != ApcfAction::CLEAR) {
        combined_data.push_back((uint8_t)org_id);
        combined_data.push_back((uint8_t)tds_flags);
        combined_data.push_back((uint8_t)tds_flags_mask);
        if (org_id == 0x02 && meta_data_type == ApcfMetaDataType::WIFI_NAN_HASH) {
          // meta data contains WIFI NAN hash
          combined_data.insert(combined_data.end(), meta_data.begin(), meta_data.end());
        }
      }
      le_scanning_interface_->EnqueueCommand(
          LeAdvFilterTransportDiscoveryDataOldBuilder::Create(action, filter_index, combined_data),
          module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
    }
  }

  void update_ad_type_filter(
      ApcfAction action,
      uint8_t filter_index,
      uint8_t ad_type,
      std::vector<uint8_t> data,
      std::vector<uint8_t> data_mask) {
    if (!is_ad_type_filter_supported_) {
      log::error("AD type filter isn't supported");
      return;
    }

    if (data.size() != data_mask.size()) {
      log::error("ad type mask should have the same length as ad type data");
      return;
    }
    std::vector<uint8_t> combined_data = {};
    if (action != ApcfAction::CLEAR) {
      combined_data.push_back((uint8_t)ad_type);
      combined_data.push_back((uint8_t)(data.size()));
      if (data.size() != 0) {
        combined_data.insert(combined_data.end(), data.begin(), data.end());
        combined_data.insert(combined_data.end(), data_mask.begin(), data_mask.end());
      }
    }

    le_scanning_interface_->EnqueueCommand(
        LeAdvFilterADTypeBuilder::Create(action, filter_index, combined_data),
        module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
  }

  void batch_scan_set_storage_parameter(
      uint8_t batch_scan_full_max,
      uint8_t batch_scan_truncated_max,
      uint8_t batch_scan_notify_threshold,
      ScannerId scanner_id) {
    if (!is_batch_scan_supported_) {
      log::warn("Batch scan is not supported");
      return;
    }
    // scanner id for OnBatchScanThresholdCrossed
    batch_scan_config_.ref_value = scanner_id;

    if (batch_scan_config_.current_state == BatchScanState::ERROR_STATE ||
        batch_scan_config_.current_state == BatchScanState::DISABLED_STATE ||
        batch_scan_config_.current_state == BatchScanState::DISABLE_CALLED) {
      batch_scan_config_.current_state = BatchScanState::ENABLE_CALLED;
      le_scanning_interface_->EnqueueCommand(
          LeBatchScanEnableBuilder::Create(Enable::ENABLED),
          module_handler_->BindOnceOn(this, &impl::on_batch_scan_enable_complete));
    }

    le_scanning_interface_->EnqueueCommand(
        LeBatchScanSetStorageParametersBuilder::Create(
            batch_scan_full_max, batch_scan_truncated_max, batch_scan_notify_threshold),
        module_handler_->BindOnceOn(this, &impl::on_batch_scan_complete));
  }

  void batch_scan_enable(
      BatchScanMode scan_mode,
      uint32_t duty_cycle_scan_window_slots,
      uint32_t duty_cycle_scan_interval_slots,
      BatchScanDiscardRule batch_scan_discard_rule) {
    if (!is_batch_scan_supported_) {
      log::warn("Batch scan is not supported");
      return;
    }

    if (batch_scan_config_.current_state == BatchScanState::ERROR_STATE ||
        batch_scan_config_.current_state == BatchScanState::DISABLED_STATE ||
        batch_scan_config_.current_state == BatchScanState::DISABLE_CALLED) {
      batch_scan_config_.current_state = BatchScanState::ENABLE_CALLED;
      le_scanning_interface_->EnqueueCommand(
          LeBatchScanEnableBuilder::Create(Enable::ENABLED),
          module_handler_->BindOnceOn(this, &impl::on_batch_scan_enable_complete));
    }

    batch_scan_config_.scan_mode = scan_mode;
    batch_scan_config_.scan_interval = duty_cycle_scan_interval_slots;
    batch_scan_config_.scan_window = duty_cycle_scan_window_slots;
    batch_scan_config_.discard_rule = batch_scan_discard_rule;
    /* This command starts batch scanning, if enabled */
    batch_scan_set_scan_parameter(
        scan_mode, duty_cycle_scan_window_slots, duty_cycle_scan_interval_slots, batch_scan_discard_rule);
  }

  void batch_scan_disable() {
    if (!is_batch_scan_supported_) {
      log::warn("Batch scan is not supported");
      return;
    }
    batch_scan_config_.current_state = BatchScanState::DISABLE_CALLED;
    batch_scan_set_scan_parameter(
        BatchScanMode::DISABLE,
        batch_scan_config_.scan_window,
        batch_scan_config_.scan_interval,
        batch_scan_config_.discard_rule);
  }

  void batch_scan_set_scan_parameter(
      BatchScanMode scan_mode,
      uint32_t duty_cycle_scan_window_slots,
      uint32_t duty_cycle_scan_interval_slots,
      BatchScanDiscardRule batch_scan_discard_rule) {
    if (!is_batch_scan_supported_) {
      log::warn("Batch scan is not supported");
      return;
    }
    PeerAddressType own_address_type = PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS;
    if (own_address_type_ == OwnAddressType::RANDOM_DEVICE_ADDRESS ||
        own_address_type_ == OwnAddressType::RESOLVABLE_OR_RANDOM_ADDRESS) {
      own_address_type = PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS;
    }
    uint8_t truncated_mode_enabled = 0x00;
    uint8_t full_mode_enabled = 0x00;
    if (scan_mode == BatchScanMode::TRUNCATED || scan_mode == BatchScanMode::TRUNCATED_AND_FULL) {
      truncated_mode_enabled = 0x01;
    }
    if (scan_mode == BatchScanMode::FULL || scan_mode == BatchScanMode::TRUNCATED_AND_FULL) {
      full_mode_enabled = 0x01;
    }

    if (scan_mode == BatchScanMode::DISABLE) {
      le_scanning_interface_->EnqueueCommand(
          LeBatchScanSetScanParametersBuilder::Create(
              truncated_mode_enabled,
              full_mode_enabled,
              duty_cycle_scan_window_slots,
              duty_cycle_scan_interval_slots,
              own_address_type,
              batch_scan_discard_rule),
          module_handler_->BindOnceOn(this, &impl::on_batch_scan_disable_complete));
    } else {
      le_scanning_interface_->EnqueueCommand(
          LeBatchScanSetScanParametersBuilder::Create(
              truncated_mode_enabled,
              full_mode_enabled,
              duty_cycle_scan_window_slots,
              duty_cycle_scan_interval_slots,
              own_address_type,
              batch_scan_discard_rule),
          module_handler_->BindOnceOn(this, &impl::on_batch_scan_complete));
    }
  }

  void batch_scan_read_results(ScannerId scanner_id, uint16_t total_num_of_records, BatchScanMode scan_mode) {
    if (!is_batch_scan_supported_) {
      log::warn("Batch scan is not supported");
      int status = static_cast<int>(ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
      scanning_callbacks_->OnBatchScanReports(scanner_id, status, 0, 0, {});
      return;
    }

    if (scan_mode != BatchScanMode::FULL && scan_mode != BatchScanMode::TRUNCATED) {
      log::warn("Invalid scan mode {}", (uint16_t)scan_mode);
      int status = static_cast<int>(ErrorCode::INVALID_HCI_COMMAND_PARAMETERS);
      scanning_callbacks_->OnBatchScanReports(scanner_id, status, 0, 0, {});
      return;
    }

    if (batch_scan_result_cache_.find(scanner_id) == batch_scan_result_cache_.end()) {
      std::vector<uint8_t> empty_data = {};
      batch_scan_result_cache_.emplace(scanner_id, empty_data);
    }

    le_scanning_interface_->EnqueueCommand(
        LeBatchScanReadResultParametersBuilder::Create(static_cast<BatchScanDataRead>(scan_mode)),
        module_handler_->BindOnceOn(this, &impl::on_batch_scan_read_result_complete, scanner_id, total_num_of_records));
  }

  void start_sync(
      uint8_t sid, const AddressWithType& address_with_type, uint16_t skip, uint16_t timeout, int request_id) {
    if (!is_periodic_advertising_sync_transfer_sender_supported_) {
      log::warn("PAST sender not supported on this device");
      int status = static_cast<int>(ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
      scanning_callbacks_->OnPeriodicSyncStarted(request_id, status, -1, sid, address_with_type, 0, 0);
      return;
    }
    PeriodicSyncStates request{
        .request_id = request_id,
        .advertiser_sid = sid,
        .address_with_type = address_with_type,
        .sync_handle = 0,
        .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
    };
    periodic_sync_manager_.StartSync(request, skip, timeout);
  }

  void stop_sync(uint16_t handle) {
    if (!is_periodic_advertising_sync_transfer_sender_supported_) {
      log::warn("PAST sender not supported on this device");
      return;
    }
    periodic_sync_manager_.StopSync(handle);
  }

  void cancel_create_sync(uint8_t sid, const Address& address) {
    if (!is_periodic_advertising_sync_transfer_sender_supported_) {
      log::warn("PAST sender not supported on this device");
      return;
    }
    periodic_sync_manager_.CancelCreateSync(sid, address);
  }

  void transfer_sync(
      const Address& address,
      uint16_t connection_handle,
      uint16_t service_data,
      uint16_t sync_handle,
      int pa_source) {
    if (!is_periodic_advertising_sync_transfer_sender_supported_) {
      log::warn("PAST sender not supported on this device");
      int status = static_cast<int>(ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
      scanning_callbacks_->OnPeriodicSyncTransferred(pa_source, status, address);
      return;
    }
    if (connection_handle == 0xFFFF) {
      log::error("[PAST]: Invalid connection handle or no LE ACL link");
      int status = static_cast<int>(ErrorCode::UNKNOWN_CONNECTION);
      scanning_callbacks_->OnPeriodicSyncTransferred(pa_source, status, address);
      return;
    }
    periodic_sync_manager_.TransferSync(address, service_data, sync_handle, pa_source, connection_handle);
  }

  void transfer_set_info(
      const Address& address,
      uint16_t connection_handle,
      uint16_t service_data,
      uint8_t adv_handle,
      int pa_source) {
    if (!is_periodic_advertising_sync_transfer_sender_supported_) {
      log::warn("PAST sender not supported on this device");
      int status = static_cast<int>(ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
      scanning_callbacks_->OnPeriodicSyncTransferred(pa_source, status, address);
      return;
    }
    if (connection_handle == 0xFFFF) {
      log::error("[PAST]:Invalid connection handle or no LE ACL link");
      int status = static_cast<int>(ErrorCode::UNKNOWN_CONNECTION);
      scanning_callbacks_->OnPeriodicSyncTransferred(pa_source, status, address);
      return;
    }
    periodic_sync_manager_.SyncSetInfo(address, service_data, adv_handle, pa_source, connection_handle);
  }

  void sync_tx_parameters(const Address& address, uint8_t mode, uint16_t skip, uint16_t timeout, int reg_id) {
    if (!is_periodic_advertising_sync_transfer_sender_supported_) {
      log::warn("PAST sender not supported on this device");
      int status = static_cast<int>(ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
      AddressWithType address_with_type(address, AddressType::RANDOM_DEVICE_ADDRESS);
      scanning_callbacks_->OnPeriodicSyncStarted(reg_id, status, -1, -1, address_with_type, 0, 0);
      return;
    }
    periodic_sync_manager_.SyncTxParameters(address, mode, skip, timeout, reg_id);
  }

  void track_advertiser(uint8_t filter_index, ScannerId scanner_id) {
    if (total_num_of_advt_tracked_ <= 0) {
      log::warn("advertisement tracking is not supported");
      AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info = {};
      on_found_on_lost_info.scanner_id = scanner_id;
      on_found_on_lost_info.advertiser_info_present = AdvtInfoPresent::NO_ADVT_INFO_PRESENT;
      scanning_callbacks_->OnTrackAdvFoundLost(on_found_on_lost_info);
      return;
    } else if (tracker_id_map_.size() >= total_num_of_advt_tracked_) {
      AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info = {};
      on_found_on_lost_info.scanner_id = scanner_id;
      on_found_on_lost_info.advertiser_info_present = AdvtInfoPresent::NO_ADVT_INFO_PRESENT;
      scanning_callbacks_->OnTrackAdvFoundLost(on_found_on_lost_info);
      return;
    }
    log::info(
        "track_advertiser scanner_id {}, filter_index {}",
        (uint16_t)scanner_id,
        (uint16_t)filter_index);
    tracker_id_map_[filter_index] = scanner_id;
  }

  void register_scanning_callback(ScanningCallback* scanning_callbacks) {
    scanning_callbacks_ = scanning_callbacks;
    periodic_sync_manager_.SetScanningCallback(scanning_callbacks_);
  }

  bool is_ad_type_filter_supported() {
    return is_ad_type_filter_supported_;
  }

  void on_set_scan_parameter_complete(CommandCompleteView view) {
    switch (view.GetCommandOpCode()) {
      case (OpCode::LE_SET_SCAN_PARAMETERS): {
        auto status_view = LeSetScanParametersCompleteView::Create(view);
        log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
        if (status_view.GetStatus() != ErrorCode::SUCCESS) {
          log::info(
              "Receive set scan parameter complete with error code {}",
              ErrorCodeText(status_view.GetStatus()));
        }
      } break;
      case (OpCode::LE_EXTENDED_SCAN_PARAMS): {
        auto status_view = LeExtendedScanParamsCompleteView::Create(view);
        log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
        if (status_view.GetStatus() != ErrorCode::SUCCESS) {
          log::info(
              "Receive extended scan parameter complete with error code {}",
              ErrorCodeText(status_view.GetStatus()));
        }
      } break;
      case (OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS): {
        auto status_view = LeSetExtendedScanParametersCompleteView::Create(view);
        log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
        if (status_view.GetStatus() != ErrorCode::SUCCESS) {
          log::info(
              "Receive set extended scan parameter complete with error code {}",
              ErrorCodeText(status_view.GetStatus()));
        }
      } break;
      default:
        log::fatal("Unhandled event {}", OpCodeText(view.GetCommandOpCode()));
    }
  }

  void on_advertising_filter_complete(CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto status_view = LeAdvFilterCompleteView::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()));
    }

    ApcfOpcode apcf_opcode = status_view.GetApcfOpcode();
    switch (apcf_opcode) {
      case ApcfOpcode::ENABLE: {
        auto complete_view = LeAdvFilterEnableCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterEnable(complete_view.GetApcfEnable(), (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::SET_FILTERING_PARAMETERS: {
        auto complete_view = LeAdvFilterSetFilteringParametersCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterParamSetup(
            complete_view.GetApcfAvailableSpaces(), complete_view.GetApcfAction(), (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::BROADCASTER_ADDRESS: {
        auto complete_view = LeAdvFilterBroadcasterAddressCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterConfigCallback(
            ApcfFilterType::BROADCASTER_ADDRESS,
            complete_view.GetApcfAvailableSpaces(),
            complete_view.GetApcfAction(),
            (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::SERVICE_UUID: {
        auto complete_view = LeAdvFilterServiceUuidCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterConfigCallback(
            ApcfFilterType::SERVICE_UUID,
            complete_view.GetApcfAvailableSpaces(),
            complete_view.GetApcfAction(),
            (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::SERVICE_SOLICITATION_UUID: {
        auto complete_view = LeAdvFilterSolicitationUuidCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterConfigCallback(
            ApcfFilterType::SERVICE_SOLICITATION_UUID,
            complete_view.GetApcfAvailableSpaces(),
            complete_view.GetApcfAction(),
            (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::LOCAL_NAME: {
        auto complete_view = LeAdvFilterLocalNameCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterConfigCallback(
            ApcfFilterType::LOCAL_NAME,
            complete_view.GetApcfAvailableSpaces(),
            complete_view.GetApcfAction(),
            (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::MANUFACTURER_DATA: {
        auto complete_view = LeAdvFilterManufacturerDataCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterConfigCallback(
            ApcfFilterType::MANUFACTURER_DATA,
            complete_view.GetApcfAvailableSpaces(),
            complete_view.GetApcfAction(),
            (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::SERVICE_DATA: {
        auto complete_view = LeAdvFilterServiceDataCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterConfigCallback(
            ApcfFilterType::SERVICE_DATA,
            complete_view.GetApcfAvailableSpaces(),
            complete_view.GetApcfAction(),
            (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::TRANSPORT_DISCOVERY_DATA: {
        auto complete_view = LeAdvFilterTransportDiscoveryDataCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterConfigCallback(
            ApcfFilterType::TRANSPORT_DISCOVERY_DATA,
            complete_view.GetApcfAvailableSpaces(),
            complete_view.GetApcfAction(),
            (uint8_t)complete_view.GetStatus());
      } break;
      case ApcfOpcode::AD_TYPE: {
        auto complete_view = LeAdvFilterADTypeCompleteView::Create(status_view);
        log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
        scanning_callbacks_->OnFilterConfigCallback(
            ApcfFilterType::AD_TYPE,
            complete_view.GetApcfAvailableSpaces(),
            complete_view.GetApcfAction(),
            (uint8_t)complete_view.GetStatus());
      } break;
      default:
        log::warn("Unexpected event type {}", OpCodeText(view.GetCommandOpCode()));
    }
  }

  void on_apcf_read_extended_features_complete(CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto status_view = LeAdvFilterCompleteView::Create(view);
    if (!status_view.IsValid()) {
      log::warn("Can not get valid LeAdvFilterCompleteView, return");
      return;
    }
    if (status_view.GetStatus() != ErrorCode::SUCCESS) {
      log::warn(
          "Got a Command complete {}, status {}",
          OpCodeText(view.GetCommandOpCode()),
          ErrorCodeText(status_view.GetStatus()));
      return;
    }
    auto complete_view = LeAdvFilterReadExtendedFeaturesCompleteView::Create(status_view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    is_transport_discovery_data_filter_supported_ =
        complete_view.GetTransportDiscoveryDataFilter() == 1;
    is_ad_type_filter_supported_ = complete_view.GetAdTypeFilter() == 1;
    log::info(
        "set is_ad_type_filter_supported_ to {} & is_transport_discovery_data_filter_supported_ to "
        "{}",
        is_ad_type_filter_supported_,
        is_transport_discovery_data_filter_supported_);
  }

  void on_batch_scan_complete(CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto status_view = LeBatchScanCompleteView::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 {}, batch_scan_opcode {}",
          OpCodeText(view.GetCommandOpCode()),
          ErrorCodeText(status_view.GetStatus()),
          BatchScanOpcodeText(status_view.GetBatchScanOpcode()));
    }
  }

  void on_batch_scan_enable_complete(CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto status_view = LeBatchScanCompleteView::Create(view);
    log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
    auto complete_view = LeBatchScanEnableCompleteView::Create(status_view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    if (status_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info(
          "Got batch scan enable complete, status {}", ErrorCodeText(status_view.GetStatus()));
      batch_scan_config_.current_state = BatchScanState::ERROR_STATE;
    } else {
      batch_scan_config_.current_state = BatchScanState::ENABLED_STATE;
    }
  }

  void on_batch_scan_disable_complete(CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto status_view = LeBatchScanCompleteView::Create(view);
    log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
    auto complete_view = LeBatchScanSetScanParametersCompleteView::Create(status_view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    log::assert_that(
        status_view.GetStatus() == ErrorCode::SUCCESS,
        "assert failed: status_view.GetStatus() == ErrorCode::SUCCESS");
    batch_scan_config_.current_state = BatchScanState::DISABLED_STATE;
  }

  void on_batch_scan_read_result_complete(
      ScannerId scanner_id, uint16_t total_num_of_records, CommandCompleteView view) {
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    auto status_view = LeBatchScanCompleteView::Create(view);
    log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
    auto complete_view = LeBatchScanReadResultParametersCompleteRawView::Create(status_view);
    log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      log::info(
          "Got batch scan read result complete, status {}", ErrorCodeText(status_view.GetStatus()));
    }
    uint8_t num_of_records = complete_view.GetNumOfRecords();
    auto report_format = complete_view.GetBatchScanDataRead();
    if (num_of_records == 0) {
      scanning_callbacks_->OnBatchScanReports(
          scanner_id, 0x00, (int)report_format, total_num_of_records, batch_scan_result_cache_[scanner_id]);
      batch_scan_result_cache_.erase(scanner_id);
    } else {
      auto raw_data = complete_view.GetRawData();
      batch_scan_result_cache_[scanner_id].insert(
          batch_scan_result_cache_[scanner_id].end(), raw_data.begin(), raw_data.end());
      total_num_of_records += num_of_records;
      batch_scan_read_results(scanner_id, total_num_of_records, static_cast<BatchScanMode>(report_format));
    }
  }

  void on_storage_threshold_breach(VendorSpecificEventView /* event */) {
    if (batch_scan_config_.ref_value == kInvalidScannerId) {
      log::warn("storage threshold was not set !!");
      return;
    }
    scanning_callbacks_->OnBatchScanThresholdCrossed(static_cast<int>(batch_scan_config_.ref_value));
  }

  void on_advertisement_tracking(VendorSpecificEventView event) {
    auto view = LEAdvertisementTrackingEventView::Create(event);
    log::assert_that(view.IsValid(), "assert failed: view.IsValid()");
    uint8_t filter_index = view.GetApcfFilterIndex();
    if (tracker_id_map_.find(filter_index) == tracker_id_map_.end()) {
      log::warn("Advertisement track for filter_index {} is not register", (uint16_t)filter_index);
      return;
    }
    AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info = {};
    on_found_on_lost_info.scanner_id = tracker_id_map_[filter_index];
    on_found_on_lost_info.filter_index = filter_index;
    on_found_on_lost_info.advertiser_state = view.GetAdvertiserState();
    on_found_on_lost_info.advertiser_address = view.GetAdvertiserAddress();
    on_found_on_lost_info.advertiser_address_type = view.GetAdvertiserAddressType();
    on_found_on_lost_info.advertiser_info_present = view.GetAdvtInfoPresent();
    /* Extract the adv info details */
    if (on_found_on_lost_info.advertiser_info_present == AdvtInfoPresent::ADVT_INFO_PRESENT) {
      auto info_view = LEAdvertisementTrackingWithInfoEventView::Create(view);
      log::assert_that(info_view.IsValid(), "assert failed: info_view.IsValid()");
      on_found_on_lost_info.tx_power = info_view.GetTxPower();
      on_found_on_lost_info.rssi = info_view.GetRssi();
      on_found_on_lost_info.time_stamp = info_view.GetTimestamp();
      auto adv_data = info_view.GetAdvPacket();
      on_found_on_lost_info.adv_packet.reserve(adv_data.size());
      on_found_on_lost_info.adv_packet.insert(on_found_on_lost_info.adv_packet.end(), adv_data.begin(), adv_data.end());
      auto scan_rsp_data = info_view.GetScanResponse();
      on_found_on_lost_info.scan_response.reserve(scan_rsp_data.size());
      on_found_on_lost_info.scan_response.insert(
          on_found_on_lost_info.scan_response.end(), scan_rsp_data.begin(), scan_rsp_data.end());
    }
    scanning_callbacks_->OnTrackAdvFoundLost(on_found_on_lost_info);
  }

  void OnPause() override {
    if (!address_manager_registered_) {
      log::warn("Unregistered!");
      return;
    }
    paused_ = true;
    scan_on_resume_ = is_scanning_;
    stop_scan();
    ack_pause();
  }

  void ack_pause() {
    le_address_manager_->AckPause(this);
  }

  void OnResume() override {
    if (!address_manager_registered_) {
      log::warn("Unregistered!");
      return;
    }
    paused_ = false;
    if (scan_on_resume_ == true) {
      scan_on_resume_ = false;
      start_scan();
    }
    le_address_manager_->AckResume(this);
  }

  ScanApiType api_type_;

  Module* module_;
  os::Handler* module_handler_;
  HciLayer* hci_layer_;
  Controller* controller_;
  AclManager* acl_manager_;
  VendorSpecificEventManager* vendor_specific_event_manager_;
  storage::StorageModule* storage_module_;
  LeScanningInterface* le_scanning_interface_;
  LeAddressManager* le_address_manager_;
  bool address_manager_registered_ = false;
  NullScanningCallback null_scanning_callback_;
  ScanningCallback* scanning_callbacks_ = &null_scanning_callback_;
  PeriodicSyncManager periodic_sync_manager_{&null_scanning_callback_};
  std::vector<Scanner> scanners_;
  bool is_scanning_ = false;
  bool scan_on_resume_ = false;
  bool paused_ = false;
  LeScanningReassembler scanning_reassembler_;
  bool is_filter_supported_ = false;
  bool is_ad_type_filter_supported_ = false;
  bool is_batch_scan_supported_ = false;
  bool is_periodic_advertising_sync_transfer_sender_supported_ = false;
  bool is_transport_discovery_data_filter_supported_ = false;

  LeScanType le_scan_type_ = LeScanType::ACTIVE;
  uint32_t interval_ms_{1000};
  uint16_t window_ms_{1000};
  uint8_t phy_{(uint8_t)PhyType::LE_1M};
  OwnAddressType own_address_type_{OwnAddressType::PUBLIC_DEVICE_ADDRESS};
  LeScanningFilterPolicy filter_policy_{LeScanningFilterPolicy::ACCEPT_ALL};
  BatchScanConfig batch_scan_config_;
  std::map<ScannerId, std::vector<uint8_t>> batch_scan_result_cache_;
  std::unordered_map<uint8_t, ScannerId> tracker_id_map_;
  uint16_t total_num_of_advt_tracked_ = 0x00;
  int8_t le_rx_path_loss_comp_ = 0;
};

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

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

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

void LeScanningManager::Stop() {
  pimpl_->stop();
  pimpl_.reset();
}

std::string LeScanningManager::ToString() const {
  return "Le Scanning Manager";
}

void LeScanningManager::RegisterScanner(Uuid app_uuid) {
  CallOn(pimpl_.get(), &impl::register_scanner, app_uuid);
}

void LeScanningManager::Unregister(ScannerId scanner_id) {
  CallOn(pimpl_.get(), &impl::unregister_scanner, scanner_id);
}

void LeScanningManager::Scan(bool start) {
  CallOn(pimpl_.get(), &impl::scan, start);
}

void LeScanningManager::SetScanParameters(
    ScannerId scanner_id,
    LeScanType scan_type,
    uint16_t scan_interval,
    uint16_t scan_window,
    uint8_t scan_phy) {
  CallOn(
      pimpl_.get(),
      &impl::set_scan_parameters,
      scanner_id,
      scan_type,
      scan_interval,
      scan_window,
      scan_phy);
}

void LeScanningManager::SetScanFilterPolicy(LeScanningFilterPolicy filter_policy) {
  CallOn(pimpl_.get(), &impl::set_scan_filter_policy, filter_policy);
}

void LeScanningManager::ScanFilterEnable(bool enable) {
  CallOn(pimpl_.get(), &impl::scan_filter_enable, enable);
}

void LeScanningManager::ScanFilterParameterSetup(
    ApcfAction action, uint8_t filter_index, AdvertisingFilterParameter advertising_filter_parameter) {
  CallOn(pimpl_.get(), &impl::scan_filter_parameter_setup, action, filter_index, advertising_filter_parameter);
}

void LeScanningManager::ScanFilterAdd(
    uint8_t filter_index, std::vector<AdvertisingPacketContentFilterCommand> filters) {
  CallOn(pimpl_.get(), &impl::scan_filter_add, filter_index, filters);
}

void LeScanningManager::BatchScanConifgStorage(
    uint8_t batch_scan_full_max,
    uint8_t batch_scan_truncated_max,
    uint8_t batch_scan_notify_threshold,
    ScannerId scanner_id) {
  CallOn(
      pimpl_.get(),
      &impl::batch_scan_set_storage_parameter,
      batch_scan_full_max,
      batch_scan_truncated_max,
      batch_scan_notify_threshold,
      scanner_id);
}

void LeScanningManager::BatchScanEnable(
    BatchScanMode scan_mode,
    uint32_t duty_cycle_scan_window_slots,
    uint32_t duty_cycle_scan_interval_slots,
    BatchScanDiscardRule batch_scan_discard_rule) {
  CallOn(
      pimpl_.get(),
      &impl::batch_scan_enable,
      scan_mode,
      duty_cycle_scan_window_slots,
      duty_cycle_scan_interval_slots,
      batch_scan_discard_rule);
}

void LeScanningManager::BatchScanDisable() {
  CallOn(pimpl_.get(), &impl::batch_scan_disable);
}

void LeScanningManager::BatchScanReadReport(ScannerId scanner_id, BatchScanMode scan_mode) {
  CallOn(pimpl_.get(), &impl::batch_scan_read_results, scanner_id, 0, scan_mode);
}

void LeScanningManager::StartSync(
    uint8_t sid, const AddressWithType& address_with_type, uint16_t skip, uint16_t timeout, int reg_id) {
  CallOn(pimpl_.get(), &impl::start_sync, sid, address_with_type, skip, timeout, reg_id);
}

void LeScanningManager::StopSync(uint16_t handle) {
  CallOn(pimpl_.get(), &impl::stop_sync, handle);
}

void LeScanningManager::CancelCreateSync(uint8_t sid, const Address& address) {
  CallOn(pimpl_.get(), &impl::cancel_create_sync, sid, address);
}

void LeScanningManager::TransferSync(
    const Address& address,
    uint16_t handle,
    uint16_t service_data,
    uint16_t sync_handle,
    int pa_source) {
  CallOn(pimpl_.get(), &impl::transfer_sync, address, handle, service_data, sync_handle, pa_source);
}

void LeScanningManager::TransferSetInfo(
    const Address& address,
    uint16_t handle,
    uint16_t service_data,
    uint8_t adv_handle,
    int pa_source) {
  CallOn(
      pimpl_.get(), &impl::transfer_set_info, address, handle, service_data, adv_handle, pa_source);
}

void LeScanningManager::SyncTxParameters(
    const Address& address, uint8_t mode, uint16_t skip, uint16_t timeout, int reg_id) {
  CallOn(pimpl_.get(), &impl::sync_tx_parameters, address, mode, skip, timeout, reg_id);
}

void LeScanningManager::TrackAdvertiser(uint8_t filter_index, ScannerId scanner_id) {
  CallOn(pimpl_.get(), &impl::track_advertiser, filter_index, scanner_id);
}

void LeScanningManager::RegisterScanningCallback(ScanningCallback* scanning_callback) {
  CallOn(pimpl_.get(), &impl::register_scanning_callback, scanning_callback);
}

bool LeScanningManager::IsAdTypeFilterSupported() const {
  return pimpl_->is_ad_type_filter_supported();
}

}  // namespace hci
}  // namespace bluetooth
