From 6f69e974216a173d7762f45ec04c8a05e11ce031 Mon Sep 17 00:00:00 2001 From: Juliet Levesque Date: Mon, 12 Jun 2023 14:04:31 -0700 Subject: [PATCH] [Nearby Connections] Stop 3 AttemptsToConnect over BluetoothClassic for CancellationFlag CancellationFlags will be used to prevent crashes during the shutdown of Nearby Connections from pending tasks taking too long during the shutdown period. By using CancellationFlags, we can prevent the retries occuring during the Shutdown by short-circuiting an in flight AttemptToConnect, and checking for Cancellation before retries. Because BluetoothClassic does not use futures, the short circuit only requires a check after ConnectToService, and returning an empty socket. PiperOrigin-RevId: 539755631 --- .../mediums/bluetooth_classic.cc | 58 ++-- .../mediums/bluetooth_classic.h | 20 +- .../mediums/bluetooth_classic_test.cc | 259 ++++++++++++++++-- internal/platform/bluetooth_classic.h | 11 +- 4 files changed, 302 insertions(+), 46 deletions(-) diff --git a/connections/implementation/mediums/bluetooth_classic.cc b/connections/implementation/mediums/bluetooth_classic.cc index 42cbaa5e..ccf42d62 100644 --- a/connections/implementation/mediums/bluetooth_classic.cc +++ b/connections/implementation/mediums/bluetooth_classic.cc @@ -18,6 +18,7 @@ #include #include +#include "internal/platform/bluetooth_classic.h" #include "internal/platform/logging.h" #include "internal/platform/mutex_lock.h" #include "internal/platform/uuid.h" @@ -40,7 +41,15 @@ std::string ScanModeToString(BluetoothAdapter::ScanMode mode) { } } // namespace -BluetoothClassic::BluetoothClassic(BluetoothRadio& radio) : radio_(radio) {} +BluetoothClassic::BluetoothClassic(BluetoothRadio& radio) + : BluetoothClassic(radio, std::make_unique( + radio.GetBluetoothAdapter())) {} + +BluetoothClassic::BluetoothClassic( + BluetoothRadio& radio, std::unique_ptr medium) + : radio_(radio), + adapter_(radio_.GetBluetoothAdapter()), + medium_(std::move(medium)) {} BluetoothClassic::~BluetoothClassic() { // Destructor is not taking locks, but methods it is calling are. @@ -63,7 +72,7 @@ bool BluetoothClassic::IsAvailable() const { } bool BluetoothClassic::IsAvailableLocked() const { - return medium_.IsValid() && adapter_.IsValid() && adapter_.IsEnabled(); + return medium_->IsValid() && adapter_.IsValid() && adapter_.IsEnabled(); } bool BluetoothClassic::TurnOnDiscoverability(const std::string& device_name) { @@ -203,7 +212,7 @@ bool BluetoothClassic::StartDiscovery(DiscoveredDeviceCallback callback) { return false; } - if (!medium_.StartDiscovery(std::move(callback))) { + if (!medium_->StartDiscovery(std::move(callback))) { NEARBY_LOGS(INFO) << "Failed to start discovery of BT devices."; return false; } @@ -223,7 +232,7 @@ bool BluetoothClassic::StopDiscovery() { return false; } - if (!medium_.StopDiscovery()) { + if (!medium_->StopDiscovery()) { NEARBY_LOGS(INFO) << "Failed to stop discovery of Bluetooth devices."; return false; } @@ -264,7 +273,7 @@ bool BluetoothClassic::StartAcceptingConnections( } BluetoothServerSocket socket = - medium_.ListenForService(service_id, GenerateUuidFromString(service_id)); + medium_->ListenForService(service_id, GenerateUuidFromString(service_id)); if (!socket.IsValid()) { NEARBY_LOGS(INFO) << "Failed to start accepting Bluetooth connections for " << service_id; @@ -351,14 +360,31 @@ bool BluetoothClassic::StopAcceptingConnections(const std::string& service_id) { BluetoothSocket BluetoothClassic::Connect(BluetoothDevice& bluetooth_device, const std::string& service_id, CancellationFlag* cancellation_flag) { - for (int attempts_count = 0; attempts_count < kConnectAttemptsLimit; - attempts_count++) { + service_id_to_connect_attempts_count_map_[service_id] = 1; + while (service_id_to_connect_attempts_count_map_[service_id] <= + kConnectAttemptsLimit) { + if (cancellation_flag->Cancelled()) { + NEARBY_LOGS(WARNING) + << "Attempt #" + << service_id_to_connect_attempts_count_map_[service_id] + << ": Cannot start creating client BT socket due to cancel."; + return BluetoothSocket(); + } + + NEARBY_LOGS(INFO) << "Attempt #" + << service_id_to_connect_attempts_count_map_[service_id] + << " to connect."; auto wrapper_result = AttemptToConnect(bluetooth_device, service_id, cancellation_flag); if (wrapper_result.IsValid()) { return wrapper_result; } + + service_id_to_connect_attempts_count_map_[service_id]++; } + + NEARBY_LOGS(WARNING) << "Giving up after " << kConnectAttemptsLimit + << " attempts"; return BluetoothSocket(); } @@ -389,16 +415,16 @@ BluetoothSocket BluetoothClassic::AttemptToConnect( return socket; } - if (cancellation_flag->Cancelled()) { - NEARBY_LOGS(INFO) << "Can't create client BT socket due to cancel."; - return socket; - } - - socket = medium_.ConnectToService( + socket = medium_->ConnectToService( bluetooth_device, GenerateUuidFromString(service_id), cancellation_flag); - if (!socket.IsValid()) { + + // If the socket isn't valid or if the cancellation flag has fired during + // `ConnectToService`, return an empty socket. There is no need for a + // CancellationFlagListener because the attempt logic is not asynchronous. + if (!socket.IsValid() || cancellation_flag->Cancelled()) { NEARBY_LOGS(INFO) << "Failed to Connect via BT [service=" << service_id << "]"; + return BluetoothSocket(); } return socket; @@ -412,7 +438,7 @@ BluetoothDevice BluetoothClassic::GetRemoteDevice( return {}; } - return medium_.GetRemoteDevice(mac_address); + return medium_->GetRemoteDevice(mac_address); } std::string BluetoothClassic::GetMacAddress() const { @@ -422,7 +448,7 @@ std::string BluetoothClassic::GetMacAddress() const { return {}; } - return medium_.GetMacAddress(); + return medium_->GetMacAddress(); } std::string BluetoothClassic::GenerateUuidFromString(const std::string& data) { diff --git a/connections/implementation/mediums/bluetooth_classic.h b/connections/implementation/mediums/bluetooth_classic.h index 08a90b2d..415129ec 100644 --- a/connections/implementation/mediums/bluetooth_classic.h +++ b/connections/implementation/mediums/bluetooth_classic.h @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "absl/container/flat_hash_map.h" #include "connections/implementation/mediums/bluetooth_radio.h" @@ -43,7 +45,7 @@ class BluetoothClassic { accepted_cb = [](const std::string&, BluetoothSocket) {}; }; - explicit BluetoothClassic(BluetoothRadio& bluetooth_radio); + explicit BluetoothClassic(BluetoothRadio& radio); ~BluetoothClassic(); // Returns true, if BT communications are supported by a platform. @@ -97,7 +99,7 @@ class BluetoothClassic { // Returns true if this object owns a valid platform implementation. bool IsMediumValid() const ABSL_LOCKS_EXCLUDED(mutex_) { MutexLock lock(&mutex_); - return medium_.IsValid(); + return medium_->IsValid(); } // Returns true if this object has a valid BluetoothAdapter reference. @@ -121,6 +123,15 @@ class BluetoothClassic { BluetoothDevice GetRemoteDevice(const std::string& mac_address) ABSL_LOCKS_EXCLUDED(mutex_); + protected: + // Use for unit tests only to inject a BluetoothClassicMedium. + BluetoothClassic(BluetoothRadio& radio, + std::unique_ptr medium); + + // Used in unit tests to determine how many calls to `AttemptToConnect` + // occured during a call to `Connect`, per service id. + std::map service_id_to_connect_attempts_count_map_; + private: struct ScanInfo { bool valid = false; @@ -175,9 +186,8 @@ class BluetoothClassic { mutable Mutex mutex_; BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_); - BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_){ - radio_.GetBluetoothAdapter()}; - BluetoothClassicMedium medium_ ABSL_GUARDED_BY(mutex_){adapter_}; + BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_); + std::unique_ptr medium_ ABSL_GUARDED_BY(mutex_); // A bundle of state required to do a Bluetooth Classic scan. When non-null, // we are currently performing a Bluetooth scan. diff --git a/connections/implementation/mediums/bluetooth_classic_test.cc b/connections/implementation/mediums/bluetooth_classic_test.cc index fa1632e2..92372c68 100644 --- a/connections/implementation/mediums/bluetooth_classic_test.cc +++ b/connections/implementation/mediums/bluetooth_classic_test.cc @@ -14,7 +14,9 @@ #include "connections/implementation/mediums/bluetooth_classic.h" +#include #include +#include #include "gmock/gmock.h" #include "protobuf-matchers/protocol-buffer-matchers.h" @@ -44,6 +46,39 @@ constexpr FeatureFlags kTestCases[] = { constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000); +class FakeBluetoothClassicMedium final : public BluetoothClassicMedium { + public: + explicit FakeBluetoothClassicMedium(BluetoothAdapter& adapter) + : BluetoothClassicMedium(adapter) {} + + BluetoothSocket ConnectToService( + BluetoothDevice& remote_device, const std::string& service_uuid, + CancellationFlag* cancellation_flag) override { + if (cancel_) { + cancellation_flag->Cancel(); + } + + return BluetoothClassicMedium::ConnectToService(remote_device, service_uuid, + cancellation_flag); + } + + void CancelDuringConnectToService() { cancel_ = true; } + + private: + bool cancel_ = false; +}; + +class TestBluetoothClassic : public BluetoothClassic { + public: + TestBluetoothClassic(BluetoothRadio& radio, + std::unique_ptr medium) + : BluetoothClassic(radio, std::move(medium)) {} + + int connect_attempts_count(std::string service_id) { + return service_id_to_connect_attempts_count_map_[service_id]; + } +}; + class BluetoothClassicTest : public ::testing::TestWithParam { protected: using DiscoveryCallback = BluetoothClassicMedium::DiscoveryCallback; @@ -52,8 +87,16 @@ class BluetoothClassicTest : public ::testing::TestWithParam { env_.Start(); radio_a_ = std::make_unique(); radio_b_ = std::make_unique(); - bt_a_ = std::make_unique(*radio_a_); - bt_b_ = std::make_unique(*radio_b_); + auto medium_a = std::make_unique( + radio_a_->GetBluetoothAdapter()); + auto medium_b = std::make_unique( + radio_b_->GetBluetoothAdapter()); + medium_a_ = medium_a.get(); + medium_b_ = medium_b.get(); + bt_a_ = + std::make_unique(*radio_a_, std::move(medium_a)); + bt_b_ = + std::make_unique(*radio_b_, std::move(medium_b)); radio_a_->GetBluetoothAdapter().SetName("Device-A"); radio_b_->GetBluetoothAdapter().SetName("Device-B"); radio_a_->Enable(); @@ -77,8 +120,10 @@ class BluetoothClassicTest : public ::testing::TestWithParam { std::unique_ptr radio_a_; std::unique_ptr radio_b_; - std::unique_ptr bt_a_; - std::unique_ptr bt_b_; + FakeBluetoothClassicMedium* medium_a_ = nullptr; + FakeBluetoothClassicMedium* medium_b_ = nullptr; + std::unique_ptr bt_a_; + std::unique_ptr bt_b_; }; TEST_P(BluetoothClassicTest, CanConnect) { @@ -86,7 +131,7 @@ TEST_P(BluetoothClassicTest, CanConnect) { env_.SetFeatureFlags(feature_flags); constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - constexpr absl::string_view kServiceName{"service name"}; + constexpr absl::string_view kServiceName1{"service name"}; BluetoothRadio& radio_for_client = *radio_a_; BluetoothRadio& radio_for_server = *radio_b_; @@ -116,7 +161,7 @@ TEST_P(BluetoothClassicTest, CanConnect) { BluetoothSocket socket_for_server; CountDownLatch accept_latch(1); EXPECT_TRUE(bt_server.StartAcceptingConnections( - std::string(kServiceName), + std::string(kServiceName1), { .accepted_cb = [&socket_for_server, &accept_latch](const std::string& service_id, @@ -127,26 +172,26 @@ TEST_P(BluetoothClassicTest, CanConnect) { })); CancellationFlag flag; BluetoothSocket socket_for_client = - bt_client.Connect(discovered_device, std::string(kServiceName), &flag); + bt_client.Connect(discovered_device, std::string(kServiceName1), &flag); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName))); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName1))); EXPECT_TRUE(socket_for_server.IsValid()); EXPECT_TRUE(socket_for_client.IsValid()); EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); EXPECT_TRUE(socket_for_client.GetRemoteDevice().IsValid()); } -TEST_P(BluetoothClassicTest, CanCancelConnect) { +TEST_P(BluetoothClassicTest, CanCancelBeforeConnect) { FeatureFlags feature_flags = GetParam(); env_.SetFeatureFlags(feature_flags); constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - constexpr absl::string_view kServiceName{"service name"}; + constexpr absl::string_view kServiceName1{"service name"}; BluetoothRadio& radio_for_client = *radio_a_; BluetoothRadio& radio_for_server = *radio_b_; - BluetoothClassic& bt_client = *bt_a_; - BluetoothClassic& bt_server = *bt_b_; + TestBluetoothClassic& bt_client = *bt_a_; + TestBluetoothClassic& bt_server = *bt_b_; EXPECT_TRUE(radio_for_client.IsEnabled()); EXPECT_TRUE(radio_for_server.IsEnabled()); @@ -171,7 +216,7 @@ TEST_P(BluetoothClassicTest, CanCancelConnect) { BluetoothSocket socket_for_server; CountDownLatch accept_latch(1); EXPECT_TRUE(bt_server.StartAcceptingConnections( - std::string(kServiceName), + std::string(kServiceName1), { .accepted_cb = [&socket_for_server, &accept_latch](const std::string& service_id, @@ -182,20 +227,196 @@ TEST_P(BluetoothClassicTest, CanCancelConnect) { })); CancellationFlag flag(true); BluetoothSocket socket_for_client = - bt_client.Connect(discovered_device, std::string(kServiceName), &flag); + bt_client.Connect(discovered_device, std::string(kServiceName1), &flag); // If FeatureFlag is disabled, Cancelled is false as no-op. if (!feature_flags.enable_cancellation_flag) { EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName))); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName1))); EXPECT_TRUE(socket_for_server.IsValid()); EXPECT_TRUE(socket_for_client.IsValid()); EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); EXPECT_TRUE(socket_for_client.GetRemoteDevice().IsValid()); } else { EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName))); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName1))); EXPECT_FALSE(socket_for_server.IsValid()); EXPECT_FALSE(socket_for_client.IsValid()); + + // Expect an invalid socket from stopping during the first attempt to + // connect, because `Connect` returned immediatley when it checked for + // cancellation. + EXPECT_EQ(1, bt_client.connect_attempts_count(std::string(kServiceName1))); + } +} + +TEST_P(BluetoothClassicTest, CanCancelDuringConnect) { + FeatureFlags feature_flags = GetParam(); + env_.SetFeatureFlags(feature_flags); + + constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; + constexpr absl::string_view kServiceName1{"service name"}; + + BluetoothRadio& radio_for_client = *radio_a_; + BluetoothRadio& radio_for_server = *radio_b_; + TestBluetoothClassic& bt_client = *bt_a_; + TestBluetoothClassic& bt_server = *bt_b_; + + // Simulate the flag being cancelled during connection attempt. + medium_a_->CancelDuringConnectToService(); + + EXPECT_TRUE(radio_for_client.IsEnabled()); + EXPECT_TRUE(radio_for_server.IsEnabled()); + + EXPECT_TRUE(bt_server.TurnOnDiscoverability(std::string(kDeviceName))); + EXPECT_EQ(radio_for_server.GetBluetoothAdapter().GetName(), + std::string(kDeviceName)); + CountDownLatch latch(1); + BluetoothDevice discovered_device; + EXPECT_TRUE(bt_client.StartDiscovery({ + .device_discovered_cb = + [&latch, &discovered_device](BluetoothDevice& device) { + discovered_device = device; + NEARBY_LOG(INFO, "Discovered device=%p [impl=%p]", &device, + &device.GetImpl()); + latch.CountDown(); + }, + })); + EXPECT_TRUE(latch.Await(kWaitDuration).result()); + EXPECT_TRUE(bt_server.TurnOffDiscoverability()); + ASSERT_TRUE(discovered_device.IsValid()); + BluetoothSocket socket_for_server; + CountDownLatch accept_latch(1); + EXPECT_TRUE(bt_server.StartAcceptingConnections( + std::string(kServiceName1), + { + .accepted_cb = + [&socket_for_server, &accept_latch](const std::string& service_id, + BluetoothSocket socket) { + socket_for_server = std::move(socket); + accept_latch.CountDown(); + }, + })); + CancellationFlag flag; + BluetoothSocket socket_for_client = + bt_client.Connect(discovered_device, std::string(kServiceName1), &flag); + // If FeatureFlag is disabled, Cancelled is false as no-op. + if (!feature_flags.enable_cancellation_flag) { + EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName1))); + EXPECT_TRUE(socket_for_server.IsValid()); + EXPECT_TRUE(socket_for_client.IsValid()); + EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); + EXPECT_TRUE(socket_for_client.GetRemoteDevice().IsValid()); + } else { + EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName1))); + EXPECT_FALSE(socket_for_server.IsValid()); + EXPECT_FALSE(socket_for_client.IsValid()); + + // Since the flag was cancelled during the initial `AttemptToConnect`, + // except only one attempt instead of the usual three, because the + // cancellation flag should short-circuit the lengthy connection attempts + // during shutdown. Because of the way the iteration happens, the check for + // is cancelled happens after the counter has already been incremented, but + // before the attempt actually occurs. + EXPECT_EQ(2, bt_client.connect_attempts_count(std::string(kServiceName1))); + } +} + +TEST_P(BluetoothClassicTest, CanCancelDuringConnect_MultipleEndpoints) { + FeatureFlags feature_flags = GetParam(); + env_.SetFeatureFlags(feature_flags); + + constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; + constexpr absl::string_view kServiceName1{"service name"}; + constexpr absl::string_view kServiceName2{"anotherservice name"}; + + BluetoothRadio& radio_for_client = *radio_a_; + BluetoothRadio& radio_for_server = *radio_b_; + TestBluetoothClassic& bt_client = *bt_a_; + TestBluetoothClassic& bt_server = *bt_b_; + EXPECT_TRUE(radio_for_client.IsEnabled()); + EXPECT_TRUE(radio_for_server.IsEnabled()); + + EXPECT_TRUE(bt_server.TurnOnDiscoverability(std::string(kDeviceName))); + EXPECT_EQ(radio_for_server.GetBluetoothAdapter().GetName(), + std::string(kDeviceName)); + CountDownLatch latch(1); + BluetoothDevice discovered_device; + EXPECT_TRUE(bt_client.StartDiscovery({ + .device_discovered_cb = + [&latch, &discovered_device](BluetoothDevice& device) { + discovered_device = device; + NEARBY_LOG(INFO, "Discovered device=%p [impl=%p]", &device, + &device.GetImpl()); + latch.CountDown(); + }, + })); + EXPECT_TRUE(latch.Await(kWaitDuration).result()); + EXPECT_TRUE(bt_server.TurnOffDiscoverability()); + ASSERT_TRUE(discovered_device.IsValid()); + BluetoothSocket socket_for_server; + CountDownLatch accept_latch(1); + + EXPECT_TRUE(bt_server.StartAcceptingConnections( + std::string(kServiceName1), + { + .accepted_cb = + [&socket_for_server, &accept_latch](const std::string& service_id, + BluetoothSocket socket) { + socket_for_server = std::move(socket); + accept_latch.CountDown(); + }, + })); + CancellationFlag flag; + BluetoothSocket socket_for_client1 = + bt_client.Connect(discovered_device, std::string(kServiceName1), &flag); + + // Simulate the flag being cancelled during connection attempt to a different + // endpoint. + medium_a_->CancelDuringConnectToService(); + EXPECT_TRUE(bt_server.StartAcceptingConnections( + std::string(kServiceName2), + { + .accepted_cb = + [&socket_for_server, &accept_latch](const std::string& service_id, + BluetoothSocket socket) { + socket_for_server = std::move(socket); + accept_latch.CountDown(); + }, + })); + + BluetoothSocket socket_for_client2 = + bt_client.Connect(discovered_device, std::string(kServiceName2), &flag); + + // If FeatureFlag is disabled, Cancelled is false as no-op. + if (!feature_flags.enable_cancellation_flag) { + EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName1))); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName2))); + EXPECT_TRUE(socket_for_server.IsValid()); + EXPECT_TRUE(socket_for_client1.IsValid()); + EXPECT_TRUE(socket_for_client2.IsValid()); + EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); + EXPECT_TRUE(socket_for_client1.GetRemoteDevice().IsValid()); + EXPECT_TRUE(socket_for_client2.GetRemoteDevice().IsValid()); + } else { + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName1))); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName2))); + EXPECT_TRUE(socket_for_client1.IsValid()); + EXPECT_FALSE(socket_for_client2.IsValid()); + + // Since the flag was cancelled during the initial `AttemptToConnect`, + // except only one attempt instead of the usual three, because the + // cancellation flag should short-circuit the lengthy connection attempts + // during shutdown. Because of the way the iteration happens, the check for + // is cancelled happens after the counter has already been incremented, but + // before the attempt actually occurs. + EXPECT_EQ(2, bt_client.connect_attempts_count(std::string(kServiceName2))); + + // With the first service name, we expect one attempt count since it + // succeeded. + EXPECT_EQ(1, bt_client.connect_attempts_count(std::string(kServiceName1))); } } @@ -250,7 +471,7 @@ TEST_F(BluetoothClassicTest, CanStopDiscovery) { TEST_F(BluetoothClassicTest, CanStartAcceptingConnections) { constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - constexpr absl::string_view kServiceName{"service name"}; + constexpr absl::string_view kServiceName1{"service name"}; BluetoothRadio& radio_for_client = *radio_a_; BluetoothRadio& radio_for_server = *radio_b_; @@ -277,11 +498,11 @@ TEST_F(BluetoothClassicTest, CanStartAcceptingConnections) { EXPECT_TRUE(bt_server.TurnOffDiscoverability()); EXPECT_TRUE(discovered_device.IsValid()); EXPECT_TRUE( - bt_server.StartAcceptingConnections(std::string(kServiceName), {})); + bt_server.StartAcceptingConnections(std::string(kServiceName1), {})); // Allow StartAcceptingConnections do something, before stopping it. // This is best effort, because no callbacks are invoked in this scenario. SystemClock::Sleep(kWaitDuration); - EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName))); + EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName1))); } } // namespace diff --git a/internal/platform/bluetooth_classic.h b/internal/platform/bluetooth_classic.h index eee85f8c..1a6b81df 100644 --- a/internal/platform/bluetooth_classic.h +++ b/internal/platform/bluetooth_classic.h @@ -69,7 +69,7 @@ class BluetoothSocket final { // Socket created by a default public constructor is not valid, because // it is missing platform implementation. // The only way to obtain a valid socket is through connection, such as - // an object returned by either BluetoothClassicMedium::ConnectTotService or + // an object returned by either BluetoothClassicMedium::ConnectToService or // BluetoothServerSocket::Accept(). // These methods may also return an invalid socket if connection failed for // any reason. @@ -160,8 +160,7 @@ class BluetoothPairing final { // Container of operations that can be performed over the Bluetooth Classic // medium. -class BluetoothClassicMedium final - : public api::BluetoothClassicMedium::Observer { +class BluetoothClassicMedium : public api::BluetoothClassicMedium::Observer { public: using Platform = api::ImplementationPlatform; struct DiscoveryCallback { @@ -252,9 +251,9 @@ class BluetoothClassicMedium final // // Returns a new BluetoothSocket. On Success, BluetoothSocket::IsValid() // returns true. - BluetoothSocket ConnectToService(BluetoothDevice& remote_device, - const std::string& service_uuid, - CancellationFlag* cancellation_flag); + virtual BluetoothSocket ConnectToService(BluetoothDevice& remote_device, + const std::string& service_uuid, + CancellationFlag* cancellation_flag); // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord //