L2CAP: Add Reassembler to separate outgoing and incoming queue

Previously Scheduler handles both outgoing and incoming packet path, but
they are actually not related to each other. Separating them to
decouple. Now Scheduler only serves outgoing packets, and the new
Reassembler serves incoming packets.

Currently only basic mode is supported. When we add enhanced retransmission
mode, we add logic to it separately.

Bug: 144375926
Test: run_cert.sh and bluetooth_test_gd
Change-Id: I411c0696fc2e6c834ab11e2485ee26d36104095d
diff --git a/gd/l2cap/Android.bp b/gd/l2cap/Android.bp
index ee86f6e..b9d5f6c 100644
--- a/gd/l2cap/Android.bp
+++ b/gd/l2cap/Android.bp
@@ -18,6 +18,7 @@
         "classic/internal/signalling_manager.cc",
         "classic/l2cap_classic_module.cc",
         "internal/scheduler_fifo.cc",
+        "internal/reassembler.cc",
         "le/internal/fixed_channel_impl.cc",
         "le/internal/fixed_channel_service_manager_impl.cc",
         "le/internal/link_manager.cc",
@@ -39,6 +40,7 @@
         "classic/internal/link_manager_test.cc",
         "classic/internal/signalling_manager_test.cc",
         "internal/fixed_channel_allocator_test.cc",
+        "internal/reassembler_test.cc",
         "internal/scheduler_fifo_test.cc",
         "l2cap_packet_test.cc",
         "le/internal/fixed_channel_impl_test.cc",
diff --git a/gd/l2cap/classic/internal/link.cc b/gd/l2cap/classic/internal/link.cc
index d59d722..ebd7df1 100644
--- a/gd/l2cap/classic/internal/link.cc
+++ b/gd/l2cap/classic/internal/link.cc
@@ -34,7 +34,8 @@
            l2cap::internal::ParameterProvider* parameter_provider,
            DynamicChannelServiceManagerImpl* dynamic_service_manager,
            FixedChannelServiceManagerImpl* fixed_service_manager)
-    : l2cap_handler_(l2cap_handler), acl_connection_(std::move(acl_connection)), scheduler_(std::move(scheduler)),
+    : l2cap_handler_(l2cap_handler), acl_connection_(std::move(acl_connection)),
+      reassembler_(acl_connection_->GetAclQueueEnd(), l2cap_handler_), scheduler_(std::move(scheduler)),
       parameter_provider_(parameter_provider), dynamic_service_manager_(dynamic_service_manager),
       fixed_service_manager_(fixed_service_manager),
       signalling_manager_(l2cap_handler_, this, dynamic_service_manager_, &dynamic_channel_allocator_,
@@ -59,6 +60,7 @@
 std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid, SecurityPolicy security_policy) {
   auto channel = fixed_channel_allocator_.AllocateChannel(cid, security_policy);
   scheduler_->AttachChannel(cid, channel->GetQueueDownEnd(), cid);
+  reassembler_.AttachChannel(cid, channel->GetQueueDownEnd(), {});
   return channel;
 }
 
@@ -87,6 +89,7 @@
   auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid, security_policy);
   if (channel != nullptr) {
     scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel->GetRemoteCid());
+    reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), {});
   }
   return channel;
 }
@@ -96,6 +99,7 @@
   auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid, security_policy);
   if (channel != nullptr) {
     scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel->GetRemoteCid());
+    reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), {});
   }
   return channel;
 }
diff --git a/gd/l2cap/classic/internal/link.h b/gd/l2cap/classic/internal/link.h
index 8db82fa..fa66ba6 100644
--- a/gd/l2cap/classic/internal/link.h
+++ b/gd/l2cap/classic/internal/link.h
@@ -26,6 +26,7 @@
 #include "l2cap/classic/internal/fixed_channel_service_manager_impl.h"
 #include "l2cap/internal/fixed_channel_allocator.h"
 #include "l2cap/internal/parameter_provider.h"
+#include "l2cap/internal/reassembler.h"
 #include "l2cap/internal/scheduler.h"
 #include "os/alarm.h"
 #include "os/handler.h"
@@ -87,6 +88,7 @@
   l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{this, l2cap_handler_};
   DynamicChannelAllocator dynamic_channel_allocator_{this, l2cap_handler_};
   std::unique_ptr<hci::AclConnection> acl_connection_;
+  l2cap::internal::Reassembler reassembler_;
   std::unique_ptr<l2cap::internal::Scheduler> scheduler_;
   l2cap::internal::ParameterProvider* parameter_provider_;
   DynamicChannelServiceManagerImpl* dynamic_service_manager_;
diff --git a/gd/l2cap/internal/reassembler.cc b/gd/l2cap/internal/reassembler.cc
new file mode 100644
index 0000000..9e0a9cc
--- /dev/null
+++ b/gd/l2cap/internal/reassembler.cc
@@ -0,0 +1,92 @@
+/*
+ * 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 "l2cap/internal/reassembler.h"
+#include "common/bidi_queue.h"
+#include "l2cap/cid.h"
+#include "l2cap/l2cap_packets.h"
+#include "packet/base_packet_builder.h"
+#include "packet/packet_view.h"
+#
+
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+Reassembler::Reassembler(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler)
+    : link_queue_up_end_(link_queue_up_end), handler_(handler) {
+  ASSERT(link_queue_up_end_ != nullptr && handler_ != nullptr);
+  link_queue_up_end_->RegisterDequeue(
+      handler_, common::Bind(&Reassembler::link_queue_dequeue_callback, common::Unretained(this)));
+}
+
+Reassembler::~Reassembler() {
+  link_queue_up_end_->UnregisterDequeue();
+}
+
+void Reassembler::AttachChannel(Cid cid, Reassembler::UpperQueueDownEnd* channel_down_end,
+                                Reassembler::ChannelConfigurationOptions options) {
+  ASSERT_LOG(channel_map_.find(cid) == channel_map_.end(), "Channel is already attached");
+  auto pair = ChannelBufferAndOptions(channel_down_end, options);
+  channel_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
+                       std::forward_as_tuple(channel_down_end, options));
+}
+
+void Reassembler::DetachChannel(Cid cid) {
+  ASSERT_LOG(channel_map_.find(cid) != channel_map_.end(), "Channel is not attached");
+  channel_map_.erase(cid);
+}
+
+void Reassembler::link_queue_dequeue_callback() {
+  auto packet = link_queue_up_end_->TryDequeue();
+  auto basic_frame_view = BasicFrameView::Create(*packet);
+  if (!basic_frame_view.IsValid()) {
+    LOG_WARN("Received an invalid basic frame");
+    return;
+  }
+  Cid cid = static_cast<Cid>(basic_frame_view.GetChannelId());
+  auto channel = channel_map_.find(cid);
+  if (channel == channel_map_.end()) {
+    LOG_WARN("Received a packet with invalid cid: %d", cid);
+    return;  // Channel is not attached to scheduler
+  }
+
+  auto channel_mode = channel->second.options_.mode_;
+  switch (channel_mode) {
+    case RetransmissionAndFlowControlModeOption::L2CAP_BASIC:
+      handle_basic_mode_packet(cid, basic_frame_view);
+      break;
+    case RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION:
+      handle_enhanced_retransmission_mode_packet(cid, std::move(basic_frame_view));
+      break;
+    default:
+      LOG_WARN("channel mode is not supported: %d", static_cast<int>(channel_mode));
+  }
+}
+
+void Reassembler::handle_basic_mode_packet(Cid cid, const BasicFrameView& view) {
+  auto channel = channel_map_.find(cid);
+  auto& enqueue_buffer = channel->second.enqueue_buffer_;
+
+  enqueue_buffer.Enqueue(std::make_unique<PacketView<kLittleEndian>>(view.GetPayload()), handler_);
+}
+
+void Reassembler::handle_enhanced_retransmission_mode_packet(Cid cid, BasicFrameView view) {
+  LOG_ERROR("Enhanced retransmission mode is not implemented");
+}
+
+}  // namespace internal
+}  // namespace l2cap
+}  // namespace bluetooth
diff --git a/gd/l2cap/internal/reassembler.h b/gd/l2cap/internal/reassembler.h
new file mode 100644
index 0000000..4eb6f70
--- /dev/null
+++ b/gd/l2cap/internal/reassembler.h
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <unordered_map>
+#include <utility>
+
+#include "common/bidi_queue.h"
+#include "l2cap/cid.h"
+#include "l2cap/l2cap_packets.h"
+#include "l2cap/mtu.h"
+#include "os/queue.h"
+#include "packet/base_packet_builder.h"
+#include "packet/packet_view.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+
+/**
+ * Handle the reassembly of L2CAP SDU from PDU.
+ * Dequeue incoming packets from LinkQueueUpEnd, and enqueue it to ChannelQueueDownEnd. Note: If a channel
+ * cannot dequeue from ChannelQueueDownEnd so that the buffer for incoming packet is full, further incoming packets will
+ * be dropped.
+ * The Reassembler keeps the reference to ChannelImpl objects, because it needs to check channel mode and parameters.
+ */
+class Reassembler {
+ public:
+  using UpperEnqueue = packet::PacketView<packet::kLittleEndian>;
+  using UpperDequeue = packet::BasePacketBuilder;
+  using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>;
+  using LowerEnqueue = UpperDequeue;
+  using LowerDequeue = UpperEnqueue;
+  using LowerQueueUpEnd = common::BidiQueueEnd<LowerEnqueue, LowerDequeue>;
+
+  Reassembler(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler);
+  ~Reassembler();
+
+  struct ChannelConfigurationOptions {
+    Mtu incoming_mtu_ = kDefaultClassicMtu;
+    RetransmissionAndFlowControlModeOption mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
+    // TODO: Add all RetransmissionAndFlowControlConfigurationOptions
+    FcsType fcs_type_ = FcsType::NO_FCS;
+  };
+
+  /**
+   * Attach a channel for packet reassembly.
+   * If the channel is reconfigured, signalling manager should detach channel and attach channel again.
+   */
+  void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, ChannelConfigurationOptions options);
+
+  /**
+   * Detach a channel for packet reassembly. Incoming packets won't be delivered to the specified cid.
+   */
+  void DetachChannel(Cid cid);
+
+ private:
+  struct ChannelBufferAndOptions {
+    ChannelBufferAndOptions(UpperQueueDownEnd* queue_end, ChannelConfigurationOptions options)
+        : enqueue_buffer_(queue_end), options_(std::move(options)) {}
+    os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_;
+    ChannelConfigurationOptions options_;
+  };
+
+  LowerQueueUpEnd* link_queue_up_end_;
+  os::Handler* handler_;
+  std::unordered_map<Cid, ChannelBufferAndOptions> channel_map_;
+
+  void link_queue_dequeue_callback();
+  void handle_basic_mode_packet(Cid cid, const BasicFrameView& view);
+  void handle_enhanced_retransmission_mode_packet(Cid cid, BasicFrameView view);
+};
+
+}  // namespace internal
+}  // namespace l2cap
+}  // namespace bluetooth
diff --git a/gd/l2cap/internal/reassembler_test.cc b/gd/l2cap/internal/reassembler_test.cc
new file mode 100644
index 0000000..a1352e7
--- /dev/null
+++ b/gd/l2cap/internal/reassembler_test.cc
@@ -0,0 +1,107 @@
+/*
+ * 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 "l2cap/internal/reassembler.h"
+
+#include <gtest/gtest.h>
+#include <future>
+
+#include "l2cap/l2cap_packets.h"
+#include "os/handler.h"
+#include "os/queue.h"
+#include "os/thread.h"
+#include "packet/raw_builder.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+namespace {
+std::unique_ptr<BasicFrameBuilder> CreateSampleL2capPacket(Cid cid, std::vector<uint8_t> payload) {
+  auto raw_builder = std::make_unique<packet::RawBuilder>();
+  raw_builder->AddOctets(payload);
+  return BasicFrameBuilder::Create(cid, std::move(raw_builder));
+}
+
+PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
+  auto bytes = std::make_shared<std::vector<uint8_t>>();
+  BitInserter i(*bytes);
+  bytes->reserve(packet->size());
+  packet->Serialize(i);
+  return packet::PacketView<packet::kLittleEndian>(bytes);
+}
+
+void sync_handler(os::Handler* handler) {
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
+  auto status = future.wait_for(std::chrono::milliseconds(3));
+  EXPECT_EQ(status, std::future_status::ready);
+}
+
+class L2capClassicReassemblerTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
+    user_handler_ = new os::Handler(thread_);
+    queue_handler_ = new os::Handler(thread_);
+    reassembler_ = new Reassembler(link_queue_.GetUpEnd(), queue_handler_);
+  }
+
+  void TearDown() override {
+    delete reassembler_;
+    queue_handler_->Clear();
+    user_handler_->Clear();
+    delete queue_handler_;
+    delete user_handler_;
+    delete thread_;
+  }
+
+  os::Thread* thread_ = nullptr;
+  os::Handler* user_handler_ = nullptr;
+  os::Handler* queue_handler_ = nullptr;
+  common::BidiQueue<Reassembler::LowerDequeue, Reassembler::LowerEnqueue> link_queue_{10};
+  Reassembler* reassembler_ = nullptr;
+};
+
+TEST_F(L2capClassicReassemblerTest, receive_basic_mode_packet) {
+  common::BidiQueue<Reassembler::UpperEnqueue, Reassembler::UpperDequeue> channel_one_queue_{10};
+  common::BidiQueue<Reassembler::UpperEnqueue, Reassembler::UpperDequeue> channel_two_queue_{10};
+  reassembler_->AttachChannel(1, channel_one_queue_.GetDownEnd(), {});
+  reassembler_->AttachChannel(2, channel_two_queue_.GetDownEnd(), {});
+  os::EnqueueBuffer<Reassembler::UpperEnqueue> link_queue_enqueue_buffer{link_queue_.GetDownEnd()};
+  auto packet_one = CreateSampleL2capPacket(1, {1, 2, 3});
+  auto packet_two = CreateSampleL2capPacket(2, {4, 5, 6, 7});
+  auto packet_one_view = GetPacketView(std::move(packet_one));
+  auto packet_two_view = GetPacketView(std::move(packet_two));
+  link_queue_enqueue_buffer.Enqueue(std::make_unique<Reassembler::UpperEnqueue>(packet_one_view), queue_handler_);
+  link_queue_enqueue_buffer.Enqueue(std::make_unique<Reassembler::UpperEnqueue>(packet_two_view), queue_handler_);
+  sync_handler(queue_handler_);
+  sync_handler(user_handler_);
+  sync_handler(queue_handler_);
+  auto packet = channel_one_queue_.GetUpEnd()->TryDequeue();
+  EXPECT_NE(packet, nullptr);
+  EXPECT_EQ(packet->size(), 3);
+  packet = channel_two_queue_.GetUpEnd()->TryDequeue();
+  EXPECT_NE(packet, nullptr);
+  EXPECT_EQ(packet->size(), 4);
+  reassembler_->DetachChannel(1);
+  reassembler_->DetachChannel(2);
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace l2cap
+}  // namespace bluetooth
diff --git a/gd/l2cap/internal/scheduler_fifo.cc b/gd/l2cap/internal/scheduler_fifo.cc
index 2e26779..e2f36ee 100644
--- a/gd/l2cap/internal/scheduler_fifo.cc
+++ b/gd/l2cap/internal/scheduler_fifo.cc
@@ -24,7 +24,6 @@
 
 Fifo::~Fifo() {
   channel_queue_end_map_.clear();
-  link_queue_up_end_->UnregisterDequeue();
   if (link_queue_enqueue_registered_) {
     link_queue_up_end_->UnregisterEnqueue();
   }
@@ -68,23 +67,6 @@
   link_queue_enqueue_registered_ = true;
 }
 
-void Fifo::link_queue_dequeue_callback() {
-  auto packet = link_queue_up_end_->TryDequeue();
-  auto base_frame_view = BasicFrameView::Create(*packet);
-  if (!base_frame_view.IsValid()) {
-    return;
-  }
-  Cid cid = static_cast<Cid>(base_frame_view.GetChannelId());
-  auto channel = channel_queue_end_map_.find(cid);
-  if (channel == channel_queue_end_map_.end()) {
-    return;  // Channel is not attached to scheduler
-  }
-  auto& queue_end_and_buffer = channel->second;
-
-  queue_end_and_buffer.enqueue_buffer_.Enqueue(
-      std::make_unique<PacketView<kLittleEndian>>(base_frame_view.GetPayload()), handler_);
-}
-
 void Fifo::ChannelQueueEndAndBuffer::try_register_dequeue() {
   if (is_dequeue_registered_) {
     return;
diff --git a/gd/l2cap/internal/scheduler_fifo.h b/gd/l2cap/internal/scheduler_fifo.h
index 3f14c75..b394426 100644
--- a/gd/l2cap/internal/scheduler_fifo.h
+++ b/gd/l2cap/internal/scheduler_fifo.h
@@ -37,8 +37,6 @@
   Fifo(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler)
       : link_queue_up_end_(link_queue_up_end), handler_(handler) {
     ASSERT(link_queue_up_end_ != nullptr && handler_ != nullptr);
-    link_queue_up_end_->RegisterDequeue(handler_,
-                                        common::Bind(&Fifo::link_queue_dequeue_callback, common::Unretained(this)));
   }
 
   ~Fifo() override;
@@ -55,13 +53,12 @@
   struct ChannelQueueEndAndBuffer {
     ChannelQueueEndAndBuffer(os::Handler* handler, UpperQueueDownEnd* queue_end, Fifo* scheduler, Cid channel_id,
                              Cid remote_channel_id)
-        : handler_(handler), queue_end_(queue_end), enqueue_buffer_(queue_end), scheduler_(scheduler),
-          channel_id_(channel_id), remote_channel_id_(remote_channel_id) {
+        : handler_(handler), queue_end_(queue_end), scheduler_(scheduler), channel_id_(channel_id),
+          remote_channel_id_(remote_channel_id) {
       try_register_dequeue();
     }
     os::Handler* handler_;
     UpperQueueDownEnd* queue_end_;
-    os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_;
     constexpr static int kBufferSize = 1;
     std::queue<std::unique_ptr<UpperDequeue>> dequeue_buffer_;
     Fifo* scheduler_;
@@ -76,7 +73,6 @@
 
   std::unordered_map<Cid, ChannelQueueEndAndBuffer> channel_queue_end_map_;
   std::queue<Cid> next_to_dequeue_;
-  void link_queue_dequeue_callback();
 
   bool link_queue_enqueue_registered_ = false;
   void try_register_link_queue_enqueue();
diff --git a/gd/l2cap/internal/scheduler_fifo_test.cc b/gd/l2cap/internal/scheduler_fifo_test.cc
index fe4d149..85ef10f 100644
--- a/gd/l2cap/internal/scheduler_fifo_test.cc
+++ b/gd/l2cap/internal/scheduler_fifo_test.cc
@@ -28,20 +28,8 @@
 namespace bluetooth {
 namespace l2cap {
 namespace internal {
+namespace {
 
-std::unique_ptr<BasicFrameBuilder> CreateSampleL2capPacket(Cid cid, std::vector<uint8_t> payload) {
-  auto raw_builder = std::make_unique<packet::RawBuilder>();
-  raw_builder->AddOctets(payload);
-  return BasicFrameBuilder::Create(cid, std::move(raw_builder));
-}
-
-PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
-  auto bytes = std::make_shared<std::vector<uint8_t>>();
-  BitInserter i(*bytes);
-  bytes->reserve(packet->size());
-  packet->Serialize(i);
-  return packet::PacketView<packet::kLittleEndian>(bytes);
-}
 void sync_handler(os::Handler* handler) {
   std::promise<void> promise;
   auto future = promise.get_future();
@@ -75,31 +63,6 @@
   Fifo* fifo_ = nullptr;
 };
 
-TEST_F(L2capSchedulerFifoTest, receive_packet) {
-  common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_one_queue_{10};
-  common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_two_queue_{10};
-  fifo_->AttachChannel(1, channel_one_queue_.GetDownEnd(), 1);
-  fifo_->AttachChannel(2, channel_two_queue_.GetDownEnd(), 2);
-  os::EnqueueBuffer<Scheduler::UpperEnqueue> link_queue_enqueue_buffer{link_queue_.GetDownEnd()};
-  auto packet_one = CreateSampleL2capPacket(1, {1, 2, 3});
-  auto packet_two = CreateSampleL2capPacket(2, {4, 5, 6, 7});
-  auto packet_one_view = GetPacketView(std::move(packet_one));
-  auto packet_two_view = GetPacketView(std::move(packet_two));
-  link_queue_enqueue_buffer.Enqueue(std::make_unique<Scheduler::UpperEnqueue>(packet_one_view), queue_handler_);
-  link_queue_enqueue_buffer.Enqueue(std::make_unique<Scheduler::UpperEnqueue>(packet_two_view), queue_handler_);
-  sync_handler(queue_handler_);
-  sync_handler(user_handler_);
-  sync_handler(queue_handler_);
-  auto packet = channel_one_queue_.GetUpEnd()->TryDequeue();
-  EXPECT_NE(packet, nullptr);
-  EXPECT_EQ(packet->size(), 3);
-  packet = channel_two_queue_.GetUpEnd()->TryDequeue();
-  EXPECT_NE(packet, nullptr);
-  EXPECT_EQ(packet->size(), 4);
-  fifo_->DetachChannel(1);
-  fifo_->DetachChannel(2);
-}
-
 TEST_F(L2capSchedulerFifoTest, send_packet) {
   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_one_queue_{10};
   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_two_queue_{10};
@@ -126,6 +89,7 @@
   fifo_->DetachChannel(2);
 }
 
+}  // namespace
 }  // namespace internal
 }  // namespace l2cap
 }  // namespace bluetooth
diff --git a/gd/l2cap/mtu.h b/gd/l2cap/mtu.h
index edaecd9..30c270c 100644
--- a/gd/l2cap/mtu.h
+++ b/gd/l2cap/mtu.h
@@ -20,13 +20,13 @@
 namespace bluetooth {
 namespace l2cap {
 
-using mtu_t = uint16_t;
+using Mtu = uint16_t;
 
-constexpr mtu_t kDefaultMinimumClassicMtu = 48;
-constexpr mtu_t kDefaultMinimumLeMtu = 23;
-constexpr mtu_t kMinimumClassicMtu = 48;
-constexpr mtu_t kDefaultClassicMtu = 672;
-constexpr mtu_t kMinimumLeMtu = 23;
+constexpr Mtu kDefaultMinimumClassicMtu = 48;
+constexpr Mtu kDefaultMinimumLeMtu = 23;
+constexpr Mtu kMinimumClassicMtu = 48;
+constexpr Mtu kDefaultClassicMtu = 672;
+constexpr Mtu kMinimumLeMtu = 23;
 
 }  // namespace l2cap
 }  // namespace bluetooth