/*
 * 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.
 */

#define LOG_TAG "bt_shim_btm"

#include "main/shim/btm.h"

#include <algorithm>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <mutex>

#include "bta/include/bta_api.h"
#include "gd/hci/le_advertising_manager.h"
#include "gd/hci/le_scanning_manager.h"
#include "gd/neighbor/connectability.h"
#include "gd/neighbor/discoverability.h"
#include "gd/neighbor/inquiry.h"
#include "gd/neighbor/name.h"
#include "gd/neighbor/page.h"
#include "gd/security/security_module.h"
#include "main/shim/controller.h"
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
#include "main/shim/shim.h"
#include "stack/btm/btm_dev.h"
#include "stack/btm/btm_int_types.h"
#include "types/bluetooth/uuid.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"

#include <base/logging.h>

extern tBTM_CB btm_cb;

static constexpr size_t kRemoteDeviceNameLength = 248;

static constexpr bool kActiveScanning = true;
static constexpr bool kPassiveScanning = false;

using BtmRemoteDeviceName = tBTM_REMOTE_DEV_NAME;

extern void btm_process_cancel_complete(uint8_t status, uint8_t mode);
extern void btm_process_inq_complete(uint8_t status, uint8_t result_type);
extern void btm_ble_process_adv_addr(RawAddress& raw_address,
                                     tBLE_ADDR_TYPE* address_type);
extern void btm_ble_process_adv_pkt_cont(
    uint16_t event_type, uint8_t address_type, const RawAddress& raw_address,
    uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid,
    int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int, uint8_t data_len,
    uint8_t* data);

extern void btm_api_process_inquiry_result(const RawAddress& raw_address,
                                           uint8_t page_scan_rep_mode,
                                           DEV_CLASS device_class,
                                           uint16_t clock_offset);

extern void btm_api_process_inquiry_result_with_rssi(RawAddress raw_address,
                                                     uint8_t page_scan_rep_mode,
                                                     DEV_CLASS device_class,
                                                     uint16_t clock_offset,
                                                     int8_t rssi);

extern void btm_api_process_extended_inquiry_result(
    RawAddress raw_address, uint8_t page_scan_rep_mode, DEV_CLASS device_class,
    uint16_t clock_offset, int8_t rssi, const uint8_t* eir_data,
    size_t eir_len);

namespace bluetooth {

namespace shim {

bool Btm::ReadRemoteName::Start(RawAddress raw_address) {
  std::unique_lock<std::mutex> lock(mutex_);
  if (in_progress_) {
    return false;
  }
  raw_address_ = raw_address;
  in_progress_ = true;
  return true;
}

void Btm::ReadRemoteName::Stop() {
  std::unique_lock<std::mutex> lock(mutex_);
  raw_address_ = RawAddress::kEmpty;
  in_progress_ = false;
}

bool Btm::ReadRemoteName::IsInProgress() const { return in_progress_; }
std::string Btm::ReadRemoteName::AddressString() const {
  return raw_address_.ToString();
}

void Btm::ScanningCallbacks::OnScannerRegistered(
    const bluetooth::hci::Uuid app_uuid, bluetooth::hci::ScannerId scanner_id,
    ScanningStatus status){};

void Btm::ScanningCallbacks::OnSetScannerParameterComplete(
    bluetooth::hci::ScannerId scanner_id, ScanningStatus status){};

void Btm::ScanningCallbacks::OnScanResult(
    uint16_t event_type, uint8_t address_type, bluetooth::hci::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) {
  tBLE_ADDR_TYPE ble_address_type = static_cast<tBLE_ADDR_TYPE>(address_type);
  uint16_t extended_event_type = 0;

  RawAddress raw_address;
  RawAddress::FromString(address.ToString(), raw_address);

  if (ble_address_type != BLE_ADDR_ANONYMOUS) {
    btm_ble_process_adv_addr(raw_address, &ble_address_type);
  }

  btm_ble_process_adv_addr(raw_address, &ble_address_type);
  btm_ble_process_adv_pkt_cont(extended_event_type, ble_address_type,
                               raw_address, primary_phy, secondary_phy,
                               advertising_sid, tx_power, rssi,
                               periodic_advertising_interval,
                               advertising_data.size(), &advertising_data[0]);
}

void Btm::ScanningCallbacks::OnTrackAdvFoundLost(
    bluetooth::hci::AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info){};
void Btm::ScanningCallbacks::OnBatchScanReports(int client_if, int status,
                                                int report_format,
                                                int num_records,
                                                std::vector<uint8_t> data){};

void Btm::ScanningCallbacks::OnBatchScanThresholdCrossed(int client_if){};
void Btm::ScanningCallbacks::OnTimeout(){};
void Btm::ScanningCallbacks::OnFilterEnable(bluetooth::hci::Enable enable,
                                            uint8_t status){};
void Btm::ScanningCallbacks::OnFilterParamSetup(
    uint8_t available_spaces, bluetooth::hci::ApcfAction action,
    uint8_t status){};
void Btm::ScanningCallbacks::OnFilterConfigCallback(
    bluetooth::hci::ApcfFilterType filter_type, uint8_t available_spaces,
    bluetooth::hci::ApcfAction action, uint8_t status){};

Btm::Btm(os::Handler* handler, neighbor::InquiryModule* inquiry)
    : scanning_timer_(handler), observing_timer_(handler) {
  ASSERT(handler != nullptr);
  ASSERT(inquiry != nullptr);
  bluetooth::neighbor::InquiryCallbacks inquiry_callbacks = {
      .result = std::bind(&Btm::OnInquiryResult, this, std::placeholders::_1),
      .result_with_rssi =
          std::bind(&Btm::OnInquiryResultWithRssi, this, std::placeholders::_1),
      .extended_result =
          std::bind(&Btm::OnExtendedInquiryResult, this, std::placeholders::_1),
      .complete =
          std::bind(&Btm::OnInquiryComplete, this, std::placeholders::_1)};
  inquiry->RegisterCallbacks(std::move(inquiry_callbacks));
}

void Btm::OnInquiryResult(bluetooth::hci::InquiryResultView view) {
  for (auto& response : view.GetInquiryResults()) {
    btm_api_process_inquiry_result(
        ToRawAddress(response.bd_addr_),
        static_cast<uint8_t>(response.page_scan_repetition_mode_),
        response.class_of_device_.data(), response.clock_offset_);
  }
}

void Btm::OnInquiryResultWithRssi(
    bluetooth::hci::InquiryResultWithRssiView view) {
  for (auto& response : view.GetInquiryResults()) {
    btm_api_process_inquiry_result_with_rssi(
        ToRawAddress(response.address_),
        static_cast<uint8_t>(response.page_scan_repetition_mode_),
        response.class_of_device_.data(), response.clock_offset_,
        response.rssi_);
  }
}

void Btm::OnExtendedInquiryResult(
    bluetooth::hci::ExtendedInquiryResultView view) {
  constexpr size_t kMaxExtendedInquiryResponse = 240;
  uint8_t gap_data_buffer[kMaxExtendedInquiryResponse];
  uint8_t* data = nullptr;
  size_t data_len = 0;

  if (!view.GetExtendedInquiryResponse().empty()) {
    bzero(gap_data_buffer, sizeof(gap_data_buffer));
    uint8_t* p = gap_data_buffer;
    for (auto gap_data : view.GetExtendedInquiryResponse()) {
      *p++ = gap_data.data_.size() + sizeof(gap_data.data_type_);
      *p++ = static_cast<uint8_t>(gap_data.data_type_);
      p = (uint8_t*)memcpy(p, &gap_data.data_[0], gap_data.data_.size()) +
          gap_data.data_.size();
    }
    data = gap_data_buffer;
    data_len = p - data;
  }

  btm_api_process_extended_inquiry_result(
      ToRawAddress(view.GetAddress()),
      static_cast<uint8_t>(view.GetPageScanRepetitionMode()),
      view.GetClassOfDevice().data(), view.GetClockOffset(), view.GetRssi(),
      data, data_len);
}

void Btm::OnInquiryComplete(bluetooth::hci::ErrorCode status) {
  limited_inquiry_active_ = false;
  general_inquiry_active_ = false;
  legacy_inquiry_complete_callback_((static_cast<uint16_t>(status) == 0)
                                        ? (BTM_SUCCESS)
                                        : (BTM_ERR_PROCESSING),
                                    active_inquiry_mode_);

  active_inquiry_mode_ = kInquiryModeOff;
}

void Btm::SetStandardInquiryResultMode() {
  GetInquiry()->SetStandardInquiryResultMode();
}

void Btm::SetInquiryWithRssiResultMode() {
  GetInquiry()->SetInquiryWithRssiResultMode();
}

void Btm::SetExtendedInquiryResultMode() {
  GetInquiry()->SetExtendedInquiryResultMode();
}

void Btm::SetInterlacedInquiryScan() { GetInquiry()->SetInterlacedScan(); }

void Btm::SetStandardInquiryScan() { GetInquiry()->SetStandardScan(); }

bool Btm::IsInterlacedScanSupported() const {
  return controller_get_interface()->supports_interlaced_inquiry_scan();
}

/**
 * One shot inquiry
 */
bool Btm::StartInquiry(
    uint8_t mode, uint8_t duration, uint8_t max_responses,
    LegacyInquiryCompleteCallback legacy_inquiry_complete_callback) {
  switch (mode) {
    case kInquiryModeOff:
      LOG_INFO("%s Stopping inquiry mode", __func__);
      if (limited_inquiry_active_ || general_inquiry_active_) {
        GetInquiry()->StopInquiry();
        limited_inquiry_active_ = false;
        general_inquiry_active_ = false;
      }
      active_inquiry_mode_ = kInquiryModeOff;
      break;

    case kLimitedInquiryMode:
    case kGeneralInquiryMode: {
      if (mode == kLimitedInquiryMode) {
        LOG_INFO(

            "%s Starting limited inquiry mode duration:%hhd max responses:%hhd",
            __func__, duration, max_responses);
        limited_inquiry_active_ = true;
        GetInquiry()->StartLimitedInquiry(duration, max_responses);
        active_inquiry_mode_ = kLimitedInquiryMode;
      } else {
        LOG_INFO(

            "%s Starting general inquiry mode duration:%hhd max responses:%hhd",
            __func__, duration, max_responses);
        general_inquiry_active_ = true;
        GetInquiry()->StartGeneralInquiry(duration, max_responses);
        legacy_inquiry_complete_callback_ = legacy_inquiry_complete_callback;
      }
    } break;

    default:
      LOG_WARN("%s Unknown inquiry mode:%d", __func__, mode);
      return false;
  }
  return true;
}

void Btm::CancelInquiry() {
  LOG_INFO("%s", __func__);
  if (limited_inquiry_active_ || general_inquiry_active_) {
    GetInquiry()->StopInquiry();
    limited_inquiry_active_ = false;
    general_inquiry_active_ = false;
  }
}

bool Btm::IsInquiryActive() const {
  return IsGeneralInquiryActive() || IsLimitedInquiryActive();
}

bool Btm::IsGeneralInquiryActive() const { return general_inquiry_active_; }

bool Btm::IsLimitedInquiryActive() const { return limited_inquiry_active_; }

/**
 * Periodic
 */
bool Btm::StartPeriodicInquiry(uint8_t mode, uint8_t duration,
                               uint8_t max_responses, uint16_t max_delay,
                               uint16_t min_delay,
                               tBTM_INQ_RESULTS_CB* p_results_cb) {
  switch (mode) {
    case kInquiryModeOff:
      limited_periodic_inquiry_active_ = false;
      general_periodic_inquiry_active_ = false;
      GetInquiry()->StopPeriodicInquiry();
      break;

    case kLimitedInquiryMode:
    case kGeneralInquiryMode: {
      if (mode == kLimitedInquiryMode) {
        LOG_INFO("%s Starting limited periodic inquiry mode", __func__);
        limited_periodic_inquiry_active_ = true;
        GetInquiry()->StartLimitedPeriodicInquiry(duration, max_responses,
                                                  max_delay, min_delay);
      } else {
        LOG_INFO("%s Starting general periodic inquiry mode", __func__);
        general_periodic_inquiry_active_ = true;
        GetInquiry()->StartGeneralPeriodicInquiry(duration, max_responses,
                                                  max_delay, min_delay);
      }
    } break;

    default:
      LOG_WARN("%s Unknown inquiry mode:%d", __func__, mode);
      return false;
  }
  return true;
}

bool Btm::IsGeneralPeriodicInquiryActive() const {
  return general_periodic_inquiry_active_;
}

bool Btm::IsLimitedPeriodicInquiryActive() const {
  return limited_periodic_inquiry_active_;
}

/**
 * Discoverability
 */

bluetooth::neighbor::ScanParameters params_{
    .interval = 0,
    .window = 0,
};

void Btm::SetClassicGeneralDiscoverability(uint16_t window, uint16_t interval) {
  params_.window = window;
  params_.interval = interval;

  GetInquiry()->SetScanActivity(params_);
  GetDiscoverability()->StartGeneralDiscoverability();
}

void Btm::SetClassicLimitedDiscoverability(uint16_t window, uint16_t interval) {
  params_.window = window;
  params_.interval = interval;
  GetInquiry()->SetScanActivity(params_);
  GetDiscoverability()->StartLimitedDiscoverability();
}

void Btm::SetClassicDiscoverabilityOff() {
  GetDiscoverability()->StopDiscoverability();
}

DiscoverabilityState Btm::GetClassicDiscoverabilityState() const {
  DiscoverabilityState state{.mode = BTM_NON_DISCOVERABLE,
                             .interval = params_.interval,
                             .window = params_.window};

  if (GetDiscoverability()->IsGeneralDiscoverabilityEnabled()) {
    state.mode = BTM_GENERAL_DISCOVERABLE;
  } else if (GetDiscoverability()->IsLimitedDiscoverabilityEnabled()) {
    state.mode = BTM_LIMITED_DISCOVERABLE;
  }
  return state;
}

void Btm::SetLeGeneralDiscoverability() {
  LOG_WARN("UNIMPLEMENTED %s", __func__);
}

void Btm::SetLeLimitedDiscoverability() {
  LOG_WARN("UNIMPLEMENTED %s", __func__);
}

void Btm::SetLeDiscoverabilityOff() { LOG_WARN("UNIMPLEMENTED %s", __func__); }

DiscoverabilityState Btm::GetLeDiscoverabilityState() const {
  DiscoverabilityState state{
      .mode = kDiscoverableModeOff,
      .interval = 0,
      .window = 0,
  };
  LOG_WARN("UNIMPLEMENTED %s", __func__);
  return state;
}

/**
 * Connectability
 */
void Btm::SetClassicConnectibleOn() {
  GetConnectability()->StartConnectability();
}

void Btm::SetClassicConnectibleOff() {
  GetConnectability()->StopConnectability();
}

ConnectabilityState Btm::GetClassicConnectabilityState() const {
  ConnectabilityState state{.interval = params_.interval,
                            .window = params_.window};

  if (GetConnectability()->IsConnectable()) {
    state.mode = BTM_CONNECTABLE;
  } else {
    state.mode = BTM_NON_CONNECTABLE;
  }
  return state;
}

void Btm::SetInterlacedPageScan() { GetPage()->SetInterlacedScan(); }

void Btm::SetStandardPageScan() { GetPage()->SetStandardScan(); }

void Btm::SetLeConnectibleOn() { LOG_WARN("UNIMPLEMENTED %s", __func__); }

void Btm::SetLeConnectibleOff() { LOG_WARN("UNIMPLEMENTED %s", __func__); }

ConnectabilityState Btm::GetLeConnectabilityState() const {
  ConnectabilityState state{
      .mode = kConnectibleModeOff,
      .interval = 0,
      .window = 0,
  };
  LOG_WARN("UNIMPLEMENTED %s", __func__);
  return state;
}

bool Btm::UseLeLink(const RawAddress& raw_address) const {
  if (GetAclManager()->HACK_GetHandle(ToGdAddress(raw_address)) != 0xFFFF) {
    return false;
  }
  if (GetAclManager()->HACK_GetLeHandle(ToGdAddress(raw_address)) != 0xFFFF) {
    return true;
  }
  // TODO(hsz): use correct transport by using storage records.  For now assume
  // LE for GATT and HID.
  return true;
}

BtmStatus Btm::ReadClassicRemoteDeviceName(const RawAddress& raw_address,
                                           tBTM_CMPL_CB* callback) {
  if (!CheckClassicAclLink(raw_address)) {
    return BTM_UNKNOWN_ADDR;
  }

  if (!classic_read_remote_name_.Start(raw_address)) {
    LOG_INFO("%s Read remote name is currently busy address:%s", __func__,
             raw_address.ToString().c_str());
    return BTM_BUSY;
  }

  LOG_INFO("%s Start read name from address:%s", __func__,
           raw_address.ToString().c_str());
  GetName()->ReadRemoteNameRequest(
      ToGdAddress(raw_address), hci::PageScanRepetitionMode::R1,
      0 /* clock_offset */, hci::ClockOffsetValid::INVALID,

      base::Bind(
          [](tBTM_CMPL_CB* callback, ReadRemoteName* classic_read_remote_name,
             hci::ErrorCode status, hci::Address address,
             std::array<uint8_t, kRemoteDeviceNameLength> remote_name) {
            RawAddress raw_address = ToRawAddress(address);

            BtmRemoteDeviceName name{
                .status = (static_cast<uint8_t>(status) == 0)
                              ? (BTM_SUCCESS)
                              : (BTM_BAD_VALUE_RET),
                .bd_addr = raw_address,
                .length = kRemoteDeviceNameLength,
            };
            std::copy(remote_name.begin(), remote_name.end(),
                      name.remote_bd_name);
            LOG_INFO("%s Finish read name from address:%s name:%s", __func__,
                     address.ToString().c_str(), name.remote_bd_name);
            callback(&name);
            classic_read_remote_name->Stop();
          },
          callback, &classic_read_remote_name_),
      GetGdShimHandler());
  return BTM_CMD_STARTED;
}

BtmStatus Btm::ReadLeRemoteDeviceName(const RawAddress& raw_address,
                                      tBTM_CMPL_CB* callback) {
  if (!CheckLeAclLink(raw_address)) {
    return BTM_UNKNOWN_ADDR;
  }

  if (!le_read_remote_name_.Start(raw_address)) {
    return BTM_BUSY;
  }

  LOG_INFO("UNIMPLEMENTED %s need access to GATT module", __func__);
  return BTM_UNKNOWN_ADDR;
}

BtmStatus Btm::CancelAllReadRemoteDeviceName() {
  if (classic_read_remote_name_.IsInProgress() ||
      le_read_remote_name_.IsInProgress()) {
    if (classic_read_remote_name_.IsInProgress()) {
      hci::Address address;
      hci::Address::FromString(classic_read_remote_name_.AddressString(),
                               address);

      GetName()->CancelRemoteNameRequest(
          address,
          common::BindOnce(
              [](ReadRemoteName* classic_read_remote_name,
                 hci::ErrorCode status,
                 hci::Address address) { classic_read_remote_name->Stop(); },
              &classic_read_remote_name_),
          GetGdShimHandler());
    }
    if (le_read_remote_name_.IsInProgress()) {
      LOG_INFO("UNIMPLEMENTED %s need access to GATT module", __func__);
    }
    return BTM_UNKNOWN_ADDR;
  }
  LOG_WARN("%s Cancelling classic remote device name without one in progress",
           __func__);
  return BTM_WRONG_MODE;
}

void Btm::StartAdvertising() {
  if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
    LOG_WARN("%s Already advertising; please stop prior to starting again",
             __func__);
    return;
  }

  hci::ExtendedAdvertisingConfig config = {};
  advertiser_id_ = GetAdvertising()->ExtendedCreateAdvertiser(
      0x00, config,
      common::Bind([](hci::Address, hci::AddressType) { /*OnScan*/ }),
      common::Bind([](hci::ErrorCode, uint8_t, uint8_t) { /*OnTerminated*/ }),
      0, 0, GetGdShimHandler());
  if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
    LOG_WARN("%s Unable to start advertising", __func__);
    return;
  }
  LOG_INFO("%s Started advertising", __func__);
}

void Btm::StopAdvertising() {
  if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
    LOG_WARN("%s No active advertising", __func__);
    return;
  }
  GetAdvertising()->RemoveAdvertiser(advertiser_id_);
  advertiser_id_ = hci::LeAdvertisingManager::kInvalidId;
  LOG_INFO("%s Stopped advertising", __func__);
}

void Btm::StartConnectability() { StartAdvertising(); }

void Btm::StopConnectability() { StopAdvertising(); }

void Btm::StartActiveScanning() { StartScanning(kActiveScanning); }

void Btm::StopActiveScanning() { GetScanning()->Scan(false); }

void Btm::SetScanningTimer(uint64_t duration_ms,
                           common::OnceCallback<void()> callback) {
  scanning_timer_.Schedule(std::move(callback),
                           std::chrono::milliseconds(duration_ms));
}

void Btm::CancelScanningTimer() { scanning_timer_.Cancel(); }

void Btm::StartObserving() { StartScanning(kPassiveScanning); }

void Btm::StopObserving() { StopActiveScanning(); }

void Btm::SetObservingTimer(uint64_t duration_ms,
                            common::OnceCallback<void()> callback) {
  observing_timer_.Schedule(std::move(callback),
                            std::chrono::milliseconds(duration_ms));
}

void Btm::CancelObservingTimer() { observing_timer_.Cancel(); }

void Btm::StartScanning(bool use_active_scanning) {
  GetScanning()->RegisterScanningCallback(&scanning_callbacks_);
  GetScanning()->Scan(true);
}

size_t Btm::GetNumberOfAdvertisingInstances() const {
  return GetAdvertising()->GetNumberOfAdvertisingInstances();
}

tBTM_STATUS Btm::CreateBond(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
                            tBT_TRANSPORT transport, int device_type) {
  if (transport == BT_TRANSPORT_AUTO) {
    if (device_type & BT_DEVICE_TYPE_BLE) {
      transport = BT_TRANSPORT_LE;
    } else if (device_type & BT_DEVICE_TYPE_BREDR) {
      transport = BT_TRANSPORT_BR_EDR;
    }
    LOG_INFO("%s guessing transport as %02x ", __func__, transport);
  }

  auto security_manager = GetSecurityModule()->GetSecurityManager();
  switch (transport) {
    case BT_TRANSPORT_BR_EDR:
      security_manager->CreateBond(ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC));
      break;
    case BT_TRANSPORT_LE:
      security_manager->CreateBondLe(ToAddressWithType(bd_addr, addr_type));
      break;
    default:
      return BTM_ILLEGAL_VALUE;
  }
  return BTM_CMD_STARTED;
}

bool Btm::CancelBond(const RawAddress& bd_addr) {
  auto security_manager = GetSecurityModule()->GetSecurityManager();
  security_manager->CancelBond(ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC));
  return true;
}

bool Btm::RemoveBond(const RawAddress& bd_addr) {
  // TODO(cmanton) Check if acl is connected
  auto security_manager = GetSecurityModule()->GetSecurityManager();
  security_manager->RemoveBond(ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC));
  return true;
}

uint16_t Btm::GetAclHandle(const RawAddress& remote_bda,
                           tBT_TRANSPORT transport) {
  auto acl_manager = GetAclManager();
  if (transport == BT_TRANSPORT_BR_EDR) {
    return acl_manager->HACK_GetHandle(ToGdAddress(remote_bda));
  } else {
    return acl_manager->HACK_GetLeHandle(ToGdAddress(remote_bda));
  }
}

hci::AddressWithType Btm::GetAddressAndType(const RawAddress& bd_addr) {
  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
  if (p_dev_rec != NULL && p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
    if (!p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) {
      return ToAddressWithType(p_dev_rec->ble.identity_address_with_type.bda,
                               p_dev_rec->ble.identity_address_with_type.type);
    } else {
      return ToAddressWithType(p_dev_rec->ble.pseudo_addr,
                               p_dev_rec->ble.ble_addr_type);
    }
  }
  LOG(ERROR) << "Unknown bd_addr. Use public address";
  return ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC);
}

}  // namespace shim

}  // namespace bluetooth
