[bt][sco] Use unique_ptr/WeakPtr for ScoConnections instead of RefPtr

Model ownership of ScoConnection using std::unique_ptr and fxl::WeakPtr
instead of fbl::RefPtr. This makes the ownership model clearer and
reduces usage of fbl, which we can't use on Pigweed.

Bug: 100658
Test: fx test //src/connectivity/bluetooth/core/bt-host
Change-Id: Icce164fab33fa5733a237e77d88e738bd335999a
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/692091
Reviewed-by: Xo Wang <xow@google.com>
Commit-Queue: Ben Lawson <benlawson@google.com>
diff --git a/src/connectivity/bluetooth/core/bt-host/fidl/profile_server.cc b/src/connectivity/bluetooth/core/bt-host/fidl/profile_server.cc
index 4757c8f..51f17a3 100644
--- a/src/connectivity/bluetooth/core/bt-host/fidl/profile_server.cc
+++ b/src/connectivity/bluetooth/core/bt-host/fidl/profile_server.cc
@@ -243,7 +243,7 @@
 
 ProfileServer::ScoConnectionServer::ScoConnectionServer(
     fidl::InterfaceRequest<fuchsia::bluetooth::bredr::ScoConnection> request,
-    fbl::RefPtr<bt::sco::ScoConnection> connection)
+    fxl::WeakPtr<bt::sco::ScoConnection> connection)
     : ServerBase(this, std::move(request)), connection_(std::move(connection)) {
   binding()->set_error_handler([this](zx_status_t) { Close(ZX_ERR_CANCELED); });
 }
@@ -649,7 +649,7 @@
     return;
   }
 
-  fbl::RefPtr<bt::sco::ScoConnection> connection = std::move(result.value().first);
+  fxl::WeakPtr<bt::sco::ScoConnection> connection = std::move(result.value().first);
   const uint16_t max_tx_data_size = connection->max_tx_sdu_size();
 
   fidl::InterfaceHandle<fidlbredr::ScoConnection> sco_handle;
diff --git a/src/connectivity/bluetooth/core/bt-host/fidl/profile_server.h b/src/connectivity/bluetooth/core/bt-host/fidl/profile_server.h
index 0dd38f4..defafbad 100644
--- a/src/connectivity/bluetooth/core/bt-host/fidl/profile_server.h
+++ b/src/connectivity/bluetooth/core/bt-host/fidl/profile_server.h
@@ -46,7 +46,7 @@
   class ScoConnectionServer final : public ServerBase<fuchsia::bluetooth::bredr::ScoConnection> {
    public:
     ScoConnectionServer(fidl::InterfaceRequest<fuchsia::bluetooth::bredr::ScoConnection> request,
-                        fbl::RefPtr<bt::sco::ScoConnection> connection);
+                        fxl::WeakPtr<bt::sco::ScoConnection> connection);
     ~ScoConnectionServer() override;
     void Activate(fit::callback<void()> on_closed);
     void Read(ReadCallback callback) override;
@@ -55,7 +55,7 @@
    private:
     void TryRead();
     void Close(zx_status_t epitaph);
-    fbl::RefPtr<bt::sco::ScoConnection> connection_;
+    fxl::WeakPtr<bt::sco::ScoConnection> connection_;
     fit::callback<void()> on_closed_;
     // Non-null when a read request is waiting for an inbound packet.
     fit::callback<void(fuchsia::bluetooth::bredr::RxPacketStatus, std::vector<uint8_t>)> read_cb_;
diff --git a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection.cc b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection.cc
index 2e15cae..2aa2bcb 100644
--- a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection.cc
+++ b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection.cc
@@ -29,13 +29,6 @@
   });
 }
 
-fbl::RefPtr<ScoConnection> ScoConnection::Create(
-    std::unique_ptr<hci::Connection> connection, fit::closure deactivated_cb,
-    hci_spec::SynchronousConnectionParameters parameters, hci::ScoDataChannel* channel) {
-  return fbl::AdoptRef(
-      new ScoConnection(std::move(connection), std::move(deactivated_cb), parameters, channel));
-}
-
 ScoConnection::UniqueId ScoConnection::unique_id() const {
   // HCI connection handles are unique per controller.
   return handle();
diff --git a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection.h b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection.h
index 33c0d40..c7deff1d 100644
--- a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection.h
+++ b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection.h
@@ -9,9 +9,6 @@
 
 #include <queue>
 
-#include <fbl/ref_counted.h>
-#include <fbl/ref_ptr.h>
-
 #include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
 #include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
 #include "src/connectivity/bluetooth/core/bt-host/transport/sco_data_channel.h"
@@ -20,20 +17,19 @@
 namespace bt::sco {
 
 // ScoConnection is a wrapper around an owned SCO hci::Connection. It provides a
-// high-level interface to the underlying connection. This class implements the required ChannelT
-// template parameter methods of SocketChannelRelay and SocketFactory.
+// high-level interface to the underlying connection.
 //
 // This class is intended to be owned by a ScoConnectionManager.
-class ScoConnection final : public hci::ScoDataChannel::ConnectionInterface,
-                            public fbl::RefCounted<ScoConnection> {
+class ScoConnection final : public hci::ScoDataChannel::ConnectionInterface {
  public:
   // |connection| is the underlying connection and must have the link type kSCO or kESCO.
   // |deactivated_cb| will be called when the connection has been Deactivated and should be
   // destroyed.
-  static fbl::RefPtr<ScoConnection> Create(std::unique_ptr<hci::Connection> connection,
-                                           fit::closure deactivated_cb,
-                                           hci_spec::SynchronousConnectionParameters parameters,
-                                           hci::ScoDataChannel* channel);
+  ScoConnection(std::unique_ptr<hci::Connection> connection, fit::closure deactivated_cb,
+                hci_spec::SynchronousConnectionParameters parameters, hci::ScoDataChannel* channel);
+
+  // Destroying this object will disconnect the underlying HCI connection.
+  ~ScoConnection() override = default;
 
   hci_spec::ConnectionHandle handle() const override { return handle_; }
 
@@ -68,6 +64,8 @@
   // If an inbound packet is ready to be read, returns the packet. Otherwise, returns nullptr.
   std::unique_ptr<hci::ScoDataPacket> Read();
 
+  fxl::WeakPtr<ScoConnection> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
+
   // ScoDataChannel overrides:
   hci_spec::SynchronousConnectionParameters parameters() override;
   std::unique_ptr<hci::ScoDataPacket> GetNextOutboundPacket() override;
@@ -75,15 +73,6 @@
   void OnHciError() override;
 
  private:
-  friend class fbl::RefPtr<ScoConnection>;
-
-  explicit ScoConnection(std::unique_ptr<hci::Connection> connection, fit::closure deactivated_cb,
-                         hci_spec::SynchronousConnectionParameters parameters,
-                         hci::ScoDataChannel* channel);
-
-  // Destroying this object will disconnect the underlying HCI connection.
-  ~ScoConnection() = default;
-
   // Common clean up logic for Close() and Deactivate(). Marks connection as inactive and closes the
   // underlying connection.
   void CleanUp();
diff --git a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager.cc b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager.cc
index 8f55ef7..f0cf866 100644
--- a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager.cc
+++ b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager.cc
@@ -85,8 +85,8 @@
   // iterator, which would be invalidated by the removal.
   while (connections_.size() > 0) {
     auto pair = connections_.begin();
-    auto handle = pair->first;
-    auto conn = pair->second;
+    hci_spec::ConnectionHandle handle = pair->first;
+    ScoConnection* conn = pair->second.get();
 
     conn->Close();
     // Make sure we erase the connection if Close doesn't so the loop terminates.
@@ -117,7 +117,7 @@
                           cb(fitx::error(result.take_error()));
                           return;
                         }
-                        cb(fitx::ok(std::move(result.value().first)));
+                        cb(fitx::ok(result.value().first));
                       });
 }
 
@@ -186,15 +186,16 @@
   };
   hci_spec::SynchronousConnectionParameters conn_params =
       in_progress_request_->parameters[in_progress_request_->current_param_index];
-  auto conn = ScoConnection::Create(std::move(link), std::move(deactivated_cb), conn_params,
-                                    transport_->sco_data_channel());
+  auto conn = std::make_unique<ScoConnection>(std::move(link), std::move(deactivated_cb),
+                                              conn_params, transport_->sco_data_channel());
+  fxl::WeakPtr<ScoConnection> conn_weak = conn->GetWeakPtr();
 
-  auto [_, success] = connections_.try_emplace(connection_handle, conn);
+  auto [_, success] = connections_.try_emplace(connection_handle, std::move(conn));
   ZX_ASSERT_MSG(success, "SCO connection already exists with handle %#.4x (peer: %s)",
                 connection_handle, bt_str(peer_id_));
 
   CompleteRequest(
-      fitx::ok(std::make_pair(std::move(conn), in_progress_request_->current_param_index)));
+      fitx::ok(std::make_pair(std::move(conn_weak), in_progress_request_->current_param_index)));
 
   return hci::CommandChannel::EventCallbackResult::kContinue;
 }
diff --git a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager.h b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager.h
index a52a158..b740fb7 100644
--- a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager.h
+++ b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager.h
@@ -50,7 +50,7 @@
   // |kCanceled| if a connection was never attempted, or |kFailed| if establishing a connection
   // failed. Returns a handle that will cancel the request when dropped (if connection establishment
   // has not started).
-  using OpenConnectionResult = fitx::result<HostError, fbl::RefPtr<ScoConnection>>;
+  using OpenConnectionResult = fitx::result<HostError, fxl::WeakPtr<ScoConnection>>;
   using OpenConnectionCallback = fit::callback<void(OpenConnectionResult)>;
   RequestHandle OpenConnection(hci_spec::SynchronousConnectionParameters parameters,
                                OpenConnectionCallback callback);
@@ -64,7 +64,7 @@
   // cancel the request when destroyed (if connection establishment has not started).
   using AcceptConnectionResult =
       fitx::result<HostError,
-                   std::pair<fbl::RefPtr<ScoConnection>, size_t /*index of parameters used*/>>;
+                   std::pair<fxl::WeakPtr<ScoConnection>, size_t /*index of parameters used*/>>;
   using AcceptConnectionCallback = fit::callback<void(AcceptConnectionResult)>;
   RequestHandle AcceptConnection(std::vector<hci_spec::SynchronousConnectionParameters> parameters,
                                  AcceptConnectionCallback callback);
@@ -73,7 +73,7 @@
   using ScoRequestId = uint64_t;
   using ConnectionResult =
       fitx::result<HostError,
-                   std::pair<fbl::RefPtr<ScoConnection>, size_t /*index of parameters used*/>>;
+                   std::pair<fxl::WeakPtr<ScoConnection>, size_t /*index of parameters used*/>>;
   using ConnectionCallback = fit::callback<void(ConnectionResult)>;
 
   class ConnectionRequest final {
@@ -146,7 +146,7 @@
   std::optional<ConnectionRequest> in_progress_request_;
 
   // Holds active connections.
-  std::unordered_map<hci_spec::ConnectionHandle, fbl::RefPtr<ScoConnection>> connections_;
+  std::unordered_map<hci_spec::ConnectionHandle, std::unique_ptr<ScoConnection>> connections_;
 
   // Handler IDs for registered events
   std::vector<hci::CommandChannel::EventHandlerId> event_handler_ids_;
diff --git a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager_unittest.cc b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager_unittest.cc
index d379dbb..c2ea079 100644
--- a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager_unittest.cc
+++ b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_manager_unittest.cc
@@ -296,12 +296,13 @@
   RunLoopUntilIdle();
   ASSERT_TRUE(conn_result.has_value());
   ASSERT_TRUE(conn_result->is_ok());
+  EXPECT_TRUE(conn_result->value());
 
   EXPECT_CMD_PACKET_OUT(test_device(), testing::DisconnectPacket(kScoConnectionHandle));
   DestroyManager();
   RunLoopUntilIdle();
-  // Ref should still be valid.
-  EXPECT_TRUE(conn_result->value());
+  // WeakPtr should become invalid.
+  EXPECT_FALSE(conn_result->value());
 }
 
 TEST_F(ScoConnectionManagerTest, QueueThreeRequestsCancelsSecond) {
@@ -398,7 +399,7 @@
   RunLoopUntilIdle();
   ASSERT_TRUE(conn_result.has_value());
   ASSERT_TRUE(conn_result->is_ok());
-  fbl::RefPtr<ScoConnection> conn = std::move(conn_result->value());
+  fxl::WeakPtr<ScoConnection> conn = conn_result->value();
   EXPECT_EQ(conn->handle(), kScoConnectionHandle);
 
   auto disconn_status_packet =
diff --git a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_unittest.cc b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_unittest.cc
index 1abcecd..43efe97 100644
--- a/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_unittest.cc
+++ b/src/connectivity/bluetooth/core/bt-host/sco/sco_connection_unittest.cc
@@ -56,16 +56,16 @@
     TestingBase::TearDown();
   }
 
-  virtual fbl::RefPtr<ScoConnection> CreateScoConnection(
+  virtual std::unique_ptr<ScoConnection> CreateScoConnection(
       std::unique_ptr<hci::Connection> hci_conn) {
-    return ScoConnection::Create(
+    return std::make_unique<ScoConnection>(
         std::move(hci_conn), [this] { OnDeactivated(); },
         hci_spec::SynchronousConnectionParameters(), /*channel=*/nullptr);
   }
 
   void OnDeactivated() { deactivated_cb_count_++; }
 
-  auto sco_conn() { return sco_conn_; }
+  ScoConnection* sco_conn() { return sco_conn_.get(); }
 
   auto hci_conn() { return hci_conn_; }
 
@@ -73,19 +73,19 @@
 
  private:
   size_t deactivated_cb_count_;
-  fbl::RefPtr<ScoConnection> sco_conn_;
+  std::unique_ptr<ScoConnection> sco_conn_;
   fxl::WeakPtr<hci::ScoConnection> hci_conn_;
 };
 
 class HciScoConnectionTest : public ScoConnectionTest {
  public:
-  fbl::RefPtr<ScoConnection> CreateScoConnection(
+  std::unique_ptr<ScoConnection> CreateScoConnection(
       std::unique_ptr<hci::Connection> hci_conn) override {
     constexpr hci_spec::SynchronousConnectionParameters hci_conn_params{
         .input_data_path = hci_spec::ScoDataPath::kHci,
         .output_data_path = hci_spec::ScoDataPath::kHci,
     };
-    return ScoConnection::Create(
+    return std::make_unique<ScoConnection>(
         std::move(hci_conn), [this] { OnDeactivated(); }, hci_conn_params,
         transport()->sco_data_channel());
   }
@@ -93,7 +93,7 @@
 
 class HciScoConnectionTestWithFakeScoChannel : public ScoConnectionTest {
  public:
-  fbl::RefPtr<ScoConnection> CreateScoConnection(
+  std::unique_ptr<ScoConnection> CreateScoConnection(
       std::unique_ptr<hci::Connection> hci_conn) override {
     channel_ = std::make_unique<hci::FakeScoDataChannel>(/*mtu=*/kHciScoMtu);
 
@@ -101,7 +101,7 @@
         .input_data_path = hci_spec::ScoDataPath::kHci,
         .output_data_path = hci_spec::ScoDataPath::kHci,
     };
-    return ScoConnection::Create(
+    return std::make_unique<ScoConnection>(
         std::move(hci_conn), [this] { OnDeactivated(); }, hci_conn_params, channel_.get());
   }
 
@@ -225,7 +225,7 @@
   auto closed_cb = [&] { close_count++; };
 
   std::vector<std::unique_ptr<hci::ScoDataPacket>> packets;
-  auto rx_callback = [&packets, sco_conn = sco_conn().get()]() {
+  auto rx_callback = [&packets, sco_conn = sco_conn()->GetWeakPtr()]() {
     std::unique_ptr<hci::ScoDataPacket> packet = sco_conn->Read();
     ASSERT_TRUE(packet);
     packets.push_back(std::move(packet));
@@ -364,7 +364,7 @@
   // Queue a packet on a second connection.
   auto hci_conn_1 = std::make_unique<hci::ScoConnection>(kConnectionHandle2, DeviceAddress(),
                                                          DeviceAddress(), transport()->WeakPtr());
-  fbl::RefPtr<ScoConnection> sco_conn_1 = CreateScoConnection(std::move(hci_conn_1));
+  std::unique_ptr<ScoConnection> sco_conn_1 = CreateScoConnection(std::move(hci_conn_1));
   size_t close_count_1 = 0;
   auto closed_cb_1 = [&] { close_count_1++; };
   EXPECT_TRUE(sco_conn_1->Activate(/*rx_callback=*/[] {}, std::move(closed_cb_1)));
diff --git a/src/connectivity/bluetooth/core/bt-host/socket/socket_factory_unittest.cc b/src/connectivity/bluetooth/core/bt-host/socket/socket_factory_unittest.cc
index e622796..c4e314c 100644
--- a/src/connectivity/bluetooth/core/bt-host/socket/socket_factory_unittest.cc
+++ b/src/connectivity/bluetooth/core/bt-host/socket/socket_factory_unittest.cc
@@ -52,10 +52,7 @@
   fbl::RefPtr<l2cap::testing::FakeChannel> channel_;
 };
 
-TEST_F(SocketFactoryTest, TemplatesCompile) {
-  socket::SocketFactory<l2cap::Channel> l2cap_factory;
-  socket::SocketFactory<sco::ScoConnection> sco_factory;
-}
+TEST_F(SocketFactoryTest, TemplatesCompile) { socket::SocketFactory<l2cap::Channel> l2cap_factory; }
 
 TEST_F(SocketFactoryTest, CanCreateSocket) {
   FactoryT socket_factory;