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

Commit dc85caa4 authored by Myles Watson's avatar Myles Watson
Browse files

Move SCO handling out of the shim

Register directly for the Queue ends, and use PDL for SCO.

Bug: 283254594
Test: presubmit
Change-Id: Ia0123bbc243306f579ae35fe3abec220a5eeb40c
parent 0cbefc9f
Loading
Loading
Loading
Loading
+114 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.
 */
#pragma once

#include <gmock/gmock.h>

#include <cstdint>

#include "common/contextual_callback.h"
#include "hci/address.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "module.h"
#include "os/handler.h"

// Unit test interfaces
namespace bluetooth {
namespace hci {
namespace testing {

class MockHciLayer : public HciLayer {
 public:
  MOCK_METHOD(
      void,
      EnqueueCommand,
      (std::unique_ptr<CommandBuilder>, common::ContextualOnceCallback<void(CommandCompleteView)>),
      (override));
  MOCK_METHOD(
      void,
      EnqueueCommand,
      (std::unique_ptr<CommandBuilder>, common::ContextualOnceCallback<void(CommandStatusView)>),
      (override));
  MOCK_METHOD((common::BidiQueueEnd<AclBuilder, AclView>*), GetAclQueueEnd, (), (override));
  MOCK_METHOD((common::BidiQueueEnd<ScoBuilder, ScoView>*), GetScoQueueEnd, (), (override));
  MOCK_METHOD((common::BidiQueueEnd<IsoBuilder, IsoView>*), GetIsoQueueEnd, (), (override));
  MOCK_METHOD(
      (void),
      RegisterEventHandler,
      (EventCode, common::ContextualCallback<void(EventView)>),
      (override));
  MOCK_METHOD((void), UnregisterEventHandler, (EventCode), (override));
  MOCK_METHOD(
      (void),
      RegisterLeEventHandler,
      (SubeventCode, common::ContextualCallback<void(LeMetaEventView)>),
      (override));
  MOCK_METHOD((void), UnregisterLeEventHandler, (SubeventCode), (override));
  MOCK_METHOD(
      (SecurityInterface*),
      GetSecurityInterface,
      (common::ContextualCallback<void(EventView)> event_handler),
      (override));

  MOCK_METHOD(
      (LeSecurityInterface*),
      GetLeSecurityInterface,
      (common::ContextualCallback<void(LeMetaEventView)> event_handler),
      (override));

  MOCK_METHOD(
      (AclConnectionInterface*),
      GetAclConnectionInterface,
      (common::ContextualCallback<void(EventView)> event_handler,
       common::ContextualCallback<void(uint16_t, hci::ErrorCode)> on_disconnect,
       common::ContextualCallback<void(hci::ErrorCode, uint16_t, uint8_t, uint16_t, uint16_t)>
           on_read_remote_version_complete),
      (override));
  MOCK_METHOD((void), PutAclConnectionInterface, (), (override));

  MOCK_METHOD(
      (LeAclConnectionInterface*),
      GetLeAclConnectionInterface,
      (common::ContextualCallback<void(LeMetaEventView)> event_handler,
       common::ContextualCallback<void(uint16_t, hci::ErrorCode)> on_disconnect,
       common::ContextualCallback<void(hci::ErrorCode, uint16_t, uint8_t, uint16_t, uint16_t)>
           on_read_remote_version_complete),
      (override));
  MOCK_METHOD((void), PutLeAclConnectionInterface, (), (override));

  MOCK_METHOD(
      (LeAdvertisingInterface*),
      GetLeAdvertisingInterface,
      (common::ContextualCallback<void(LeMetaEventView)> event_handler),
      (override));

  MOCK_METHOD(
      (LeScanningInterface*),
      GetLeScanningInterface,
      (common::ContextualCallback<void(LeMetaEventView)> event_handler),
      (override));

  MOCK_METHOD(
      (LeIsoInterface*),
      GetLeIsoInterface,
      (common::ContextualCallback<void(LeMetaEventView)> event_handler),
      (override));
};

}  // namespace testing
}  // namespace hci
}  // namespace bluetooth
+0 −68
Original line number Diff line number Diff line
@@ -267,16 +267,11 @@ static bool event_already_registered_in_le_scanning_manager(
}  // namespace

namespace cpp {
bluetooth::common::BidiQueueEnd<bluetooth::hci::ScoBuilder,
                                bluetooth::hci::ScoView>* hci_sco_queue_end =
    nullptr;
bluetooth::common::BidiQueueEnd<bluetooth::hci::IsoBuilder,
                                bluetooth::hci::IsoView>* hci_iso_queue_end =
    nullptr;
static bluetooth::os::EnqueueBuffer<bluetooth::hci::IsoBuilder>*
    pending_iso_data = nullptr;
static bluetooth::os::EnqueueBuffer<bluetooth::hci::ScoBuilder>*
    pending_sco_data = nullptr;

static std::unique_ptr<bluetooth::packet::RawBuilder> MakeUniquePacket(
    const uint8_t* data, size_t len) {
@@ -376,26 +371,6 @@ static void transmit_command(const BT_HDR* command,
  }
}

static void transmit_sco_fragment(const uint8_t* stream, size_t length) {
  uint16_t handle_with_flags;
  STREAM_TO_UINT16(handle_with_flags, stream);
  uint16_t handle = HCID_GET_HANDLE(handle_with_flags);
  ASSERT_LOG(handle <= HCI_HANDLE_MAX, "Require handle <= 0x%X, but is 0x%X",
             HCI_HANDLE_MAX, handle);

  length -= 2;
  // skip data total length
  stream += 1;
  length -= 1;
  auto payload = std::vector<uint8_t>(stream, stream + length);
  auto sco_packet = bluetooth::hci::ScoBuilder::Create(
      handle, bluetooth::hci::PacketStatusFlag::CORRECTLY_RECEIVED,
      std::move(payload));

  pending_sco_data->Enqueue(std::move(sco_packet),
                            bluetooth::shim::GetGdShimHandler());
}

static void transmit_iso_fragment(const uint8_t* stream, size_t length) {
  uint16_t handle_with_flags;
  STREAM_TO_UINT16(handle_with_flags, stream);
@@ -430,23 +405,6 @@ static void register_le_event(bluetooth::hci::SubeventCode subevent_code) {
      subevent_code, handler->Bind(subevent_callback));
}

static void sco_data_callback() {
  if (hci_sco_queue_end == nullptr) {
    return;
  }
  auto packet = hci_sco_queue_end->TryDequeue();
  ASSERT(packet != nullptr);
  if (!packet->IsValid()) {
    LOG_INFO("Dropping invalid packet of size %zu", packet->size());
    return;
  }
  if (!send_data_upwards) {
    return;
  }
  auto data = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_SCO, packet.get());
  send_data_upwards.Run(FROM_HERE, data);
}

static void iso_data_callback() {
  if (hci_iso_queue_end == nullptr) {
    return;
@@ -464,16 +422,6 @@ static void iso_data_callback() {
  packet_fragmenter->reassemble_and_dispatch(data);
}

static void register_for_sco() {
  hci_sco_queue_end = bluetooth::shim::GetHciLayer()->GetScoQueueEnd();
  hci_sco_queue_end->RegisterDequeue(
      bluetooth::shim::GetGdShimHandler(),
      bluetooth::common::Bind(sco_data_callback));
  pending_sco_data =
      new bluetooth::os::EnqueueBuffer<bluetooth::hci::ScoBuilder>(
          hci_sco_queue_end);
}

static void register_for_iso() {
  hci_iso_queue_end = bluetooth::shim::GetHciLayer()->GetIsoQueueEnd();
  hci_iso_queue_end->RegisterDequeue(
@@ -485,20 +433,11 @@ static void register_for_iso() {
}

static void on_shutting_down() {
  if (pending_sco_data != nullptr) {
    pending_sco_data->Clear();
    delete pending_sco_data;
    pending_sco_data = nullptr;
  }
  if (pending_iso_data != nullptr) {
    pending_iso_data->Clear();
    delete pending_iso_data;
    pending_iso_data = nullptr;
  }
  if (hci_sco_queue_end != nullptr) {
    hci_sco_queue_end->UnregisterDequeue();
    hci_sco_queue_end = nullptr;
  }
  if (hci_iso_queue_end != nullptr) {
    hci_iso_queue_end->UnregisterDequeue();
    hci_iso_queue_end = nullptr;
@@ -551,12 +490,6 @@ static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = {
    transmit_fragment, dispatch_reassembled};

static void transmit_downward(uint16_t type, void* raw_data) {
  if (type == BT_EVT_TO_LM_HCI_SCO) {
    BT_HDR* event = static_cast<BT_HDR*>(raw_data);
    bluetooth::shim::GetGdShimHandler()->Call(
        cpp::transmit_sco_fragment, event->data + event->offset, event->len);
    return;
  }
  bluetooth::shim::GetGdShimHandler()->Call(
      packet_fragmenter->fragment_and_dispatch, static_cast<BT_HDR*>(raw_data));
}
@@ -608,7 +541,6 @@ void bluetooth::shim::hci_on_reset_complete() {
    cpp::register_le_event(subevent_code);
  }

  cpp::register_for_sco();
  cpp::register_for_iso();
}

+1 −0
Original line number Diff line number Diff line
@@ -276,6 +276,7 @@ cc_library_static {
    ],
    generated_headers: [
        "BluetoothGeneratedDumpsysDataSchema_h",
        "BluetoothGeneratedPackets_h",
    ],
    cflags: [
        /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/
+100 −4
Original line number Diff line number Diff line
@@ -32,11 +32,15 @@

#define LOG_TAG "btm_sco"

#include "common/bidi_queue.h"
#include "device/include/controller.h"
#include "device/include/device_iot_config.h"
#include "embdrv/sbc/decoder/include/oi_codec_sbc.h"
#include "embdrv/sbc/decoder/include/oi_status.h"
#include "gd/hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "hci/include/hci_layer.h"
#include "main/shim/entry.h"
#include "main/shim/hci_layer.h"
#include "osi/include/allocator.h"
#include "osi/include/log.h"
@@ -49,6 +53,7 @@
#include "stack/include/bt_hdr.h"
#include "stack/include/btm_api.h"
#include "stack/include/btm_api_types.h"
#include "stack/include/btu.h"  // do_in_main_thread
#include "stack/include/hci_error_code.h"
#include "stack/include/stack_metrics_logging.h"
#include "types/class_of_device.h"
@@ -72,6 +77,100 @@ const bluetooth::legacy::hci::Interface& GetLegacyHciInterface() {

};  // namespace

// forward declaration for dequeueing packets
void btm_route_sco_data(BT_HDR* p_msg);

namespace cpp {
constexpr size_t kBtHdrSize = sizeof(BT_HDR);
bluetooth::common::BidiQueueEnd<bluetooth::hci::ScoBuilder,
                                bluetooth::hci::ScoView>* hci_sco_queue_end =
    nullptr;
static bluetooth::os::EnqueueBuffer<bluetooth::hci::ScoBuilder>*
    pending_sco_data = nullptr;

static BT_HDR* WrapPacketAndCopy(
    uint16_t event,
    bluetooth::hci::PacketView<bluetooth::hci::kLittleEndian>* data) {
  size_t packet_size = data->size() + kBtHdrSize;
  BT_HDR* packet = reinterpret_cast<BT_HDR*>(osi_malloc(packet_size));
  packet->offset = 0;
  packet->len = data->size();
  packet->layer_specific = 0;
  packet->event = event;
  std::copy(data->begin(), data->end(), packet->data);
  return packet;
}

static void transmit_sco_fragment(const uint8_t* stream, size_t length) {
  uint16_t handle_with_flags;
  STREAM_TO_UINT16(handle_with_flags, stream);
  uint16_t handle = HCID_GET_HANDLE(handle_with_flags);
  ASSERT_LOG(handle <= HCI_HANDLE_MAX, "Require handle <= 0x%X, but is 0x%X",
             HCI_HANDLE_MAX, handle);

  length -= 2;
  // skip data total length
  stream += 1;
  length -= 1;
  auto payload = std::vector<uint8_t>(stream, stream + length);
  auto sco_packet = bluetooth::hci::ScoBuilder::Create(
      handle, bluetooth::hci::PacketStatusFlag::CORRECTLY_RECEIVED,
      std::move(payload));

  pending_sco_data->Enqueue(std::move(sco_packet),
                            bluetooth::shim::GetGdShimHandler());
}
static void sco_data_callback() {
  if (hci_sco_queue_end == nullptr) {
    return;
  }
  auto packet = hci_sco_queue_end->TryDequeue();
  ASSERT(packet != nullptr);
  if (!packet->IsValid()) {
    LOG_INFO("Dropping invalid packet of size %zu", packet->size());
    return;
  }
  auto data = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_SCO, packet.get());
  if (do_in_main_thread(FROM_HERE, base::Bind(&btm_route_sco_data, data)) !=
      BT_STATUS_SUCCESS) {
    LOG(ERROR) << __func__
               << ": do_in_main_thread failed from sco_data_callback";
  }
}
static void register_for_sco() {
  hci_sco_queue_end = bluetooth::shim::GetHciLayer()->GetScoQueueEnd();
  hci_sco_queue_end->RegisterDequeue(
      bluetooth::shim::GetGdShimHandler(),
      bluetooth::common::Bind(sco_data_callback));
  pending_sco_data =
      new bluetooth::os::EnqueueBuffer<bluetooth::hci::ScoBuilder>(
          hci_sco_queue_end);
}

static void shut_down_sco() {
  if (pending_sco_data != nullptr) {
    pending_sco_data->Clear();
    delete pending_sco_data;
    pending_sco_data = nullptr;
  }
  if (hci_sco_queue_end != nullptr) {
    hci_sco_queue_end->UnregisterDequeue();
    hci_sco_queue_end = nullptr;
  }
}
};  // namespace cpp

void tSCO_CB::Init() {
  hfp_hal_interface::init();
  def_esco_parms = esco_parameters_for_codec(
      ESCO_CODEC_CVSD_S3, hfp_hal_interface::get_offload_enabled());
  cpp::register_for_sco();
}

void tSCO_CB::Free() {
  cpp::shut_down_sco();
  bluetooth::audio::sco::cleanup();
}
/******************************************************************************/
/*               L O C A L    D A T A    D E F I N I T I O N S                */
/******************************************************************************/
@@ -382,11 +481,8 @@ void btm_send_sco_packet(std::vector<uint8_t> data) {
  }
  BT_HDR* packet = btm_sco_make_packet(std::move(data), active_sco->hci_handle);

  auto hci = bluetooth::shim::hci_layer_get_interface();

  packet->event = BT_EVT_TO_LM_HCI_SCO;

  hci->transmit_downward(packet->event, packet);
  cpp::transmit_sco_fragment(packet->data + packet->offset, packet->len);
}

// Build a SCO packet from uint8
+2 −6
Original line number Diff line number Diff line
@@ -204,13 +204,9 @@ typedef struct {
    return nullptr;
  }

  void Init() {
    hfp_hal_interface::init();
    def_esco_parms = esco_parameters_for_codec(
        ESCO_CODEC_CVSD_S3, hfp_hal_interface::get_offload_enabled());
  }
  void Init();

  void Free() { bluetooth::audio::sco::cleanup(); }
  void Free();

  uint16_t get_index(const tSCO_CONN* p_sco) const {
    CHECK(p_sco != nullptr);
Loading