Merge branch 'master' into release to roll forward up to cl/355978895.

This commit is contained in:
hai007
2021-02-08 04:25:49 -08:00
13 changed files with 317 additions and 53 deletions
+1
View File
@@ -76,6 +76,7 @@ cc_library(
"pcp_manager.h",
"service_controller.h",
"service_controller_router.h",
"stoppable_service_controller.h",
"webrtc_bwu_handler.h",
"webrtc_endpoint_channel.h",
"wifi_lan_bwu_handler.h",
+1 -4
View File
@@ -199,7 +199,7 @@ Status BasePcpHandler::WaitForResult(const std::string& method_name,
NEARBY_LOG(INFO, "No future to wait for; return with error");
return {Status::kError};
}
NEARBY_LOG(INFO, "waiting for future to complete");
NEARBY_LOG(INFO, "Waiting for future to complete: %s", method_name.c_str());
ExceptionOr<Status> result = future->Get();
if (!result.ok()) {
NEARBY_LOG(INFO, "Future:[%s] completed with exception: %d",
@@ -261,7 +261,6 @@ void BasePcpHandler::OnEncryptionSuccessRunnable(
ProcessPreConnectionInitiationFailure(
endpoint_id, connection_info.channel.get(), {Status::kEndpointIoError},
connection_info.result.lock().get());
connection_info.result.reset();
return;
}
@@ -322,7 +321,6 @@ void BasePcpHandler::OnEncryptionFailureRunnable(
ProcessPreConnectionInitiationFailure(endpoint_id, info.channel.get(),
{Status::kEndpointIoError},
info.result.lock().get());
info.result.reset();
}
Status BasePcpHandler::RequestConnection(ClientProxy* client,
@@ -1024,7 +1022,6 @@ void BasePcpHandler::ProcessTieBreakLoss(
ProcessPreConnectionInitiationFailure(endpoint_id, info->channel.get(),
{Status::kEndpointIoError},
info->result.lock().get());
info->result.reset();
ProcessPreConnectionResultFailure(client, endpoint_id);
}
+39 -3
View File
@@ -28,6 +28,7 @@
#include "core/params.h"
#include "proto/connections/offline_wire_formats.pb.h"
#include "platform/base/byte_array.h"
#include "platform/base/exception.h"
#include "platform/public/count_down_latch.h"
#include "platform/public/pipe.h"
#include "proto/connections_enums.pb.h"
@@ -72,6 +73,9 @@ class MockEndpointChannel : public BaseEndpointChannel {
ExceptionOr<ByteArray> DoRead() { return BaseEndpointChannel::Read(); }
Exception DoWrite(const ByteArray& data) {
if (broken_write_) {
return {Exception::kFailed};
}
return BaseEndpointChannel::Write(data);
}
absl::Time DoGetLastReadTimestamp() {
@@ -88,6 +92,8 @@ class MockEndpointChannel : public BaseEndpointChannel {
MOCK_METHOD(void, Pause, (), (override));
MOCK_METHOD(void, Resume, (), (override));
MOCK_METHOD(absl::Time, GetLastReadTimestamp, (), (const override));
bool broken_write_{false};
};
class MockPcpHandler : public BasePcpHandler {
@@ -311,7 +317,8 @@ class BasePcpHandlerTest
MockEndpointChannel* channel_b, ClientProxy* client,
MockPcpHandler* pcp_handler,
proto::connections::Medium connect_medium,
std::atomic_int* flag = nullptr) {
std::atomic_int* flag = nullptr,
Status expected_result = {Status::kSuccess}) {
ConnectionRequestInfo info{
.endpoint_info = ByteArray{"ABCD"},
.listener = connection_listener_,
@@ -325,7 +332,9 @@ class BasePcpHandlerTest
.WillRepeatedly(Return(true));
EXPECT_CALL(*pcp_handler, GetStrategy)
.WillRepeatedly(Return(Strategy::kP2pCluster));
EXPECT_CALL(mock_connection_listener_.initiated_cb, Call).Times(1);
if (expected_result == Status{Status::kSuccess}) {
EXPECT_CALL(mock_connection_listener_.initiated_cb, Call).Times(1);
}
// Simulate successful discovery.
auto encryption_runner = std::make_unique<EncryptionRunner>();
auto allowed_mediums = pcp_handler->GetDiscoveryMediums(client);
@@ -365,7 +374,7 @@ class BasePcpHandlerTest
}
EXPECT_EQ(
pcp_handler->RequestConnection(client, endpoint_id, info, options),
Status{Status::kSuccess});
expected_result);
NEARBY_LOG(INFO, "Stopping Encryption Runner");
}
@@ -479,6 +488,33 @@ TEST_P(BasePcpHandlerTest, RequestConnectionChangesState) {
pcp_handler.DisconnectFromEndpointManager();
}
TEST_P(BasePcpHandlerTest, IoError_RequestConnectionFails) {
std::string endpoint_id{"1234"};
ClientProxy client;
Mediums m;
EndpointChannelManager ecm;
EndpointManager em(&ecm);
BwuManager bwu(m, em, ecm, {}, {});
MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu);
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(AtLeast(1));
EXPECT_CALL(*channel_b, CloseImpl).Times(AtLeast(1));
channel_b->broken_write_ = true;
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client,
&pcp_handler, connect_medium, nullptr,
{Status::kEndpointIoError});
NEARBY_LOG(INFO, "RequestConnection complete");
channel_b->Close();
bwu.Shutdown();
pcp_handler.DisconnectFromEndpointManager();
}
TEST_P(BasePcpHandlerTest, AcceptConnectionChangesState) {
std::string endpoint_id{"1234"};
ClientProxy client;
+46 -3
View File
@@ -23,6 +23,7 @@
#include "core/internal/webrtc_bwu_handler.h"
#include "core/internal/wifi_lan_bwu_handler.h"
#include "platform/base/byte_array.h"
#include "platform/base/feature_flags.h"
#include "platform/public/count_down_latch.h"
#include "proto/connections_enums.pb.h"
#include "absl/functional/bind_front.h"
@@ -136,6 +137,11 @@ void BwuManager::InitiateBwuForEndpoint(ClientProxy* client,
if (in_progress_upgrades_.contains(endpoint_id)) {
return;
}
if (FeatureFlags::GetInstance()
.GetFlags()
.disallow_out_of_order_bwu_avail_event) {
CancelRetryUpgradeAlarm(endpoint_id);
}
auto channel = channel_manager_->GetChannelForEndpoint(endpoint_id);
@@ -311,9 +317,19 @@ void BwuManager::OnIncomingConnection(
}
const std::string& endpoint_id = introduction.endpoint_id();
auto item = in_progress_upgrades_.extract(endpoint_id);
if (item.empty()) return;
ClientProxy* mapped_client = item.mapped();
ClientProxy* mapped_client;
if (FeatureFlags::GetInstance()
.GetFlags()
.disallow_out_of_order_bwu_avail_event) {
const auto item = in_progress_upgrades_.find(endpoint_id);
if (item == in_progress_upgrades_.end()) return;
mapped_client = item->second;
} else {
auto item = in_progress_upgrades_.extract(endpoint_id);
if (item.empty()) return;
mapped_client = item.mapped();
}
CancelRetryUpgradeAlarm(endpoint_id);
if (mapped_client == nullptr) {
// This was never a fully EstablishedConnection, no need to provide a
@@ -377,11 +393,28 @@ void BwuManager::RunUpgradeProtocol(
void BwuManager::ProcessBwuPathAvailableEvent(
ClientProxy* client, const string& endpoint_id,
const UpgradePathInfo& upgrade_path_info) {
if (in_progress_upgrades_.contains(endpoint_id)) {
NEARBY_LOG(INFO, "Invoking duplicate ProcessBwuPathAvailableEvent for %s",
endpoint_id.c_str());
if (FeatureFlags::GetInstance()
.GetFlags()
.disallow_out_of_order_bwu_avail_event) {
NEARBY_LOG(WARNING,
"BandwidthUpgradeManager is ignoring bandwidth upgrade for "
"endpoint %s because we're already upgrading bandwidth for "
"that endpoint. Something may have gone wrong, as it seems "
"we're out of sync with the remote device.",
endpoint_id.c_str());
return;
}
}
Medium medium =
parser::UpgradePathInfoMediumToMedium(upgrade_path_info.medium());
if (medium_ == Medium::UNKNOWN_MEDIUM) {
SetCurrentBwuHandler(medium);
}
// Check for the correct medium so we don't process an incorrect OfflineFrame.
if (medium != medium_) {
RunUpgradeFailedProtocol(client, endpoint_id, upgrade_path_info);
@@ -395,6 +428,11 @@ void BwuManager::ProcessBwuPathAvailableEvent(
return;
}
if (FeatureFlags::GetInstance()
.GetFlags()
.disallow_out_of_order_bwu_avail_event) {
in_progress_upgrades_.emplace(endpoint_id, client);
}
RunUpgradeProtocol(client, endpoint_id, std::move(channel));
}
@@ -656,6 +694,11 @@ void BwuManager::ProcessSafeToClosePriorChannelEvent(
// Report the success to the client
client->OnBandwidthChanged(endpoint_id, channel->GetMedium());
if (FeatureFlags::GetInstance()
.GetFlags()
.disallow_out_of_order_bwu_avail_event) {
in_progress_upgrades_.erase(endpoint_id);
}
}
void BwuManager::ProcessUpgradeFailureEvent(
+20 -3
View File
@@ -24,7 +24,9 @@
#include "core/options.h"
#include "core/params.h"
#include "core/payload.h"
#include "platform/base/feature_flags.h"
#include "platform/public/logging.h"
#include "absl/memory/memory.h"
#include "absl/time/clock.h"
namespace location {
@@ -48,7 +50,15 @@ const std::size_t kMaxEndpointInfoLength = 131u;
ServiceControllerRouter::~ServiceControllerRouter() {
NEARBY_LOG(INFO, "ServiceControllerRouter going down.");
service_controller_.reset();
if (FeatureFlags::GetInstance()
.GetFlags()
.disable_released_service_controller) {
if (service_controller_) {
service_controller_->Shutdown();
}
} else {
service_controller_.reset();
}
// And make sure that cleanup is the last thing we do.
serializer_.Shutdown();
}
@@ -427,7 +437,13 @@ void ServiceControllerRouter::ReleaseServiceControllerForClient(
ClientProxy* client) {
clients_.erase(client);
// service_controller_ won't be released here. Instead, in desctructor.
// service_controller_ won't be released here. Instead, in destructor.
if (FeatureFlags::GetInstance()
.GetFlags()
.disable_released_service_controller) {
service_controller_->Shutdown();
}
if (clients_.empty()) {
current_strategy_ = Strategy{};
}
@@ -475,7 +491,8 @@ Status ServiceControllerRouter::UpdateCurrentServiceControllerAndStrategy(
return {Status::kError};
}
service_controller_.reset(service_controller_factory_());
service_controller_ = absl::make_unique<StoppableServiceController>(
service_controller_factory_());
current_strategy_ = strategy;
return {Status::kSuccess};
@@ -21,6 +21,7 @@
#include "core/internal/client_proxy.h"
#include "core/internal/service_controller.h"
#include "core/internal/stoppable_service_controller.h"
#include "core/options.h"
#include "core/params.h"
#include "platform/base/runnable.h"
@@ -119,7 +120,7 @@ class ServiceControllerRouter {
absl::flat_hash_set<ClientProxy*> clients_;
std::function<ServiceController*()> service_controller_factory_;
std::unique_ptr<ServiceController> service_controller_;
std::unique_ptr<StoppableServiceController> service_controller_;
Strategy current_strategy_;
SingleThreadExecutor serializer_;
};
@@ -50,15 +50,10 @@ const char kFakeInejctedEndpointId[] = "abcd";
// friend class to work.
class ServiceControllerRouterTest : public testing::Test {
public:
ServiceControllerRouterTest() = default;
~ServiceControllerRouterTest() override {
router_.service_controller_.release();
}
void StartAdvertising(ClientProxy* client, std::string service_id,
ConnectionOptions options, ConnectionRequestInfo info,
ResultCallback callback) {
EXPECT_CALL(mock_, StartAdvertising)
EXPECT_CALL(*mock_, StartAdvertising)
.WillOnce(Return(Status{Status::kSuccess}));
{
MutexLock lock(&mutex_);
@@ -73,7 +68,7 @@ class ServiceControllerRouterTest : public testing::Test {
}
void StopAdvertising(ClientProxy* client, ResultCallback callback) {
EXPECT_CALL(mock_, StopAdvertising).Times(1);
EXPECT_CALL(*mock_, StopAdvertising).Times(1);
{
MutexLock lock(&mutex_);
complete_ = false;
@@ -88,7 +83,7 @@ class ServiceControllerRouterTest : public testing::Test {
ConnectionOptions options,
const DiscoveryListener& listener,
const ResultCallback& callback) {
EXPECT_CALL(mock_, StartDiscovery)
EXPECT_CALL(*mock_, StartDiscovery)
.WillOnce(Return(Status{Status::kSuccess}));
{
MutexLock lock(&mutex_);
@@ -103,7 +98,7 @@ class ServiceControllerRouterTest : public testing::Test {
}
void StopDiscovery(ClientProxy* client, ResultCallback callback) {
EXPECT_CALL(mock_, StopDiscovery).Times(1);
EXPECT_CALL(*mock_, StopDiscovery).Times(1);
{
MutexLock lock(&mutex_);
complete_ = false;
@@ -117,7 +112,7 @@ class ServiceControllerRouterTest : public testing::Test {
void InjectEndpoint(ClientProxy* client, std::string service_id,
const OutOfBandConnectionMetadata& metadata,
ResultCallback callback) {
EXPECT_CALL(mock_, InjectEndpoint).Times(1);
EXPECT_CALL(*mock_, InjectEndpoint).Times(1);
{
MutexLock lock(&mutex_);
complete_ = false;
@@ -129,7 +124,7 @@ class ServiceControllerRouterTest : public testing::Test {
void RequestConnection(ClientProxy* client, const std::string& endpoint_id,
const ConnectionRequestInfo& request_info,
ResultCallback callback) {
EXPECT_CALL(mock_, RequestConnection)
EXPECT_CALL(*mock_, RequestConnection)
.WillOnce(Return(Status{Status::kSuccess}));
ConnectionOptions options;
{
@@ -154,7 +149,7 @@ class ServiceControllerRouterTest : public testing::Test {
void AcceptConnection(ClientProxy* client, const std::string endpoint_id,
const PayloadListener& listener,
const ResultCallback& callback) {
EXPECT_CALL(mock_, AcceptConnection)
EXPECT_CALL(*mock_, AcceptConnection)
.WillOnce(Return(Status{Status::kSuccess}));
// Pre-condition for successful Accept is: connection must exist.
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint_id));
@@ -174,7 +169,7 @@ class ServiceControllerRouterTest : public testing::Test {
void RejectConnection(ClientProxy* client, const std::string endpoint_id,
ResultCallback callback) {
EXPECT_CALL(mock_, RejectConnection)
EXPECT_CALL(*mock_, RejectConnection)
.WillOnce(Return(Status{Status::kSuccess}));
// Pre-condition for successful Accept is: connection must exist.
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint_id));
@@ -192,7 +187,7 @@ class ServiceControllerRouterTest : public testing::Test {
void InitiateBandwidthUpgrade(ClientProxy* client,
const std::string endpoint_id,
ResultCallback callback) {
EXPECT_CALL(mock_, InitiateBandwidthUpgrade).Times(1);
EXPECT_CALL(*mock_, InitiateBandwidthUpgrade).Times(1);
EXPECT_TRUE(client->IsConnectedToEndpoint(endpoint_id));
{
MutexLock lock(&mutex_);
@@ -206,7 +201,7 @@ class ServiceControllerRouterTest : public testing::Test {
void SendPayload(ClientProxy* client,
const std::vector<std::string>& endpoint_ids,
Payload payload, ResultCallback callback) {
EXPECT_CALL(mock_, SendPayload).Times(1);
EXPECT_CALL(*mock_, SendPayload).Times(1);
bool connected = false;
for (const auto& endpoint_id : endpoint_ids) {
@@ -225,7 +220,7 @@ class ServiceControllerRouterTest : public testing::Test {
void CancelPayload(ClientProxy* client, std::int64_t payload_id,
ResultCallback callback) {
EXPECT_CALL(mock_, CancelPayload)
EXPECT_CALL(*mock_, CancelPayload)
.WillOnce(Return(Status{Status::kSuccess}));
{
MutexLock lock(&mutex_);
@@ -239,7 +234,7 @@ class ServiceControllerRouterTest : public testing::Test {
void DisconnectFromEndpoint(ClientProxy* client,
const std::string endpoint_id,
ResultCallback callback) {
EXPECT_CALL(mock_, DisconnectFromEndpoint).Times(1);
EXPECT_CALL(*mock_, DisconnectFromEndpoint).Times(1);
EXPECT_TRUE(client->IsConnectedToEndpoint(endpoint_id));
{
MutexLock lock(&mutex_);
@@ -291,15 +286,20 @@ class ServiceControllerRouterTest : public testing::Test {
ConditionVariable cond_{&mutex_};
Status result_ ABSL_GUARDED_BY(mutex_) = {Status::kError};
bool complete_ ABSL_GUARDED_BY(mutex_) = false;
MockServiceController mock_;
// `router_` will take over ownership and delete the mock
MockServiceController* mock_ = new MockServiceController();
ClientProxy client_;
ServiceControllerRouter router_{
[this]() -> ServiceController* { return &mock_; }};
[this]() -> ServiceController* { return mock_; }};
};
namespace {
TEST_F(ServiceControllerRouterTest, CostructorDestructorWorks) { SUCCEED(); }
TEST_F(ServiceControllerRouterTest, CostructorDestructorWorks) {
// This test doesn't create `router_`, so we must clean up manually
delete mock_;
SUCCEED();
}
TEST_F(ServiceControllerRouterTest, StartAdvertisingCalled) {
StartAdvertising(&client_, kServiceId, kConnectionOptions,
@@ -0,0 +1,145 @@
// Copyright 2020 Google LLC
//
// 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
//
// https://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.
#ifndef CORE_INTERNAL_STOPPABLE_SERVICE_CONTROLLER_H_
#define CORE_INTERNAL_STOPPABLE_SERVICE_CONTROLLER_H_
#include <memory>
#include "core/internal/service_controller.h"
#include "core/status.h"
#include "platform/public/atomic_boolean.h"
namespace location {
namespace nearby {
namespace connections {
// A ServiceController proxy that can be shut down.
// When shut down, the API calls are not forwarded to the real controller.
// StoppableServiceController takes over ownership of ServiceController.
class StoppableServiceController : public ServiceController {
public:
explicit StoppableServiceController(ServiceController* controller)
: service_controller_{controller} {}
~StoppableServiceController() override = default;
void Shutdown() { stopped_.Set(true); }
Status StartAdvertising(ClientProxy* client, const std::string& service_id,
const ConnectionOptions& options,
const ConnectionRequestInfo& info) override {
if (stopped_) {
return {Status::kError};
}
return service_controller_->StartAdvertising(client, service_id, options,
info);
}
void StopAdvertising(ClientProxy* client) override {
if (stopped_) {
return;
}
service_controller_->StopAdvertising(client);
}
Status StartDiscovery(ClientProxy* client, const std::string& service_id,
const ConnectionOptions& options,
const DiscoveryListener& listener) override {
if (stopped_) {
return {Status::kError};
}
return service_controller_->StartDiscovery(client, service_id, options,
listener);
}
void StopDiscovery(ClientProxy* client) override {
if (stopped_) {
return;
}
service_controller_->StopDiscovery(client);
}
void InjectEndpoint(ClientProxy* client, const std::string& service_id,
const OutOfBandConnectionMetadata& metadata) override {
if (stopped_) {
return;
}
service_controller_->InjectEndpoint(client, service_id, metadata);
}
Status RequestConnection(ClientProxy* client, const std::string& endpoint_id,
const ConnectionRequestInfo& info,
const ConnectionOptions& options) override {
if (stopped_) {
return {Status::kError};
}
return service_controller_->RequestConnection(client, endpoint_id, info,
options);
}
Status AcceptConnection(ClientProxy* client, const std::string& endpoint_id,
const PayloadListener& listener) override {
if (stopped_) {
return {Status::kError};
}
return service_controller_->AcceptConnection(client, endpoint_id, listener);
}
Status RejectConnection(ClientProxy* client,
const std::string& endpoint_id) override {
if (stopped_) {
return {Status::kError};
}
return service_controller_->RejectConnection(client, endpoint_id);
}
void InitiateBandwidthUpgrade(ClientProxy* client,
const std::string& endpoint_id) override {
if (stopped_) {
return;
}
service_controller_->InitiateBandwidthUpgrade(client, endpoint_id);
}
void SendPayload(ClientProxy* client,
const std::vector<std::string>& endpoint_ids,
Payload payload) override {
if (stopped_) {
return;
}
service_controller_->SendPayload(client, endpoint_ids, std::move(payload));
}
Status CancelPayload(ClientProxy* client, Payload::Id payload_id) override {
if (stopped_) {
return {Status::kError};
}
return service_controller_->CancelPayload(client, payload_id);
}
void DisconnectFromEndpoint(ClientProxy* client,
const std::string& endpoint_id) override {
if (stopped_) {
return;
}
service_controller_->DisconnectFromEndpoint(client, endpoint_id);
}
private:
std::unique_ptr<ServiceController> service_controller_;
AtomicBoolean stopped_{false};
};
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CORE_INTERNAL_STOPPABLE_SERVICE_CONTROLLER_H_
+7
View File
@@ -28,6 +28,13 @@ class FeatureFlags {
struct Flags {
bool enable_cancellation_flag = false;
bool resume_before_disconnect = true;
// Disable ServiceController API (using StoppableServiceController) when
// ServiceController is released to prevent calls to that API from
// other threads.
bool disable_released_service_controller = true;
// Ignore subsequent BWU Available events when we're still processing the
// first one.
bool disallow_out_of_order_bwu_avail_event = true;
};
static const FeatureFlags& GetInstance() {
+2
View File
@@ -38,6 +38,8 @@ class AtomicBoolean final : public api::AtomicBoolean {
bool Get() const override { return impl_->Get(); }
bool Set(bool value) override { return impl_->Set(value); }
explicit operator bool() const { return Get(); }
private:
std::unique_ptr<api::AtomicBoolean> impl_;
};
@@ -33,6 +33,17 @@ TEST(AtomicBooleanTest, GetReturnsWhatWasSet) {
EXPECT_TRUE(value.Get());
}
TEST(AtomicBooleanTest, ImplicitGetTrueValue) {
AtomicBoolean value(true);
EXPECT_TRUE(value);
}
TEST(AtomicBooleanTest, ImplicitGetFalseValue) {
AtomicBoolean value(false);
EXPECT_FALSE(value);
}
} // namespace
} // namespace nearby
} // namespace location
+18 -19
View File
@@ -33,18 +33,12 @@ BluetoothSocket BluetoothClassicMedium::ConnectToService(
}
bool BluetoothClassicMedium::StartDiscovery(DiscoveryCallback callback) {
{
MutexLock lock(&mutex_);
if (discovery_enabled_) {
NEARBY_LOG(INFO, "BT Discovery already enabled; impl=%p", &GetImpl());
return false;
}
discovery_callback_ = std::move(callback);
devices_.clear();
discovery_enabled_ = true;
NEARBY_LOG(INFO, "BT Discovery enabled; impl=%p", &GetImpl());
MutexLock lock(&mutex_);
if (discovery_enabled_) {
NEARBY_LOG(INFO, "BT Discovery already enabled; impl=%p", &GetImpl());
return false;
}
return impl_->StartDiscovery({
bool success = impl_->StartDiscovery({
.device_discovered_cb =
[this](api::BluetoothDevice& device) {
MutexLock lock(&mutex_);
@@ -82,17 +76,22 @@ bool BluetoothClassicMedium::StartDiscovery(DiscoveryCallback callback) {
discovery_callback_.device_lost_cb(context.device);
},
});
if (success) {
discovery_callback_ = std::move(callback);
devices_.clear();
discovery_enabled_ = true;
NEARBY_LOG(INFO, "BT Discovery enabled; impl=%p", &GetImpl());
}
return success;
}
bool BluetoothClassicMedium::StopDiscovery() {
{
MutexLock lock(&mutex_);
if (!discovery_enabled_) return true;
discovery_enabled_ = false;
discovery_callback_ = {};
devices_.clear();
NEARBY_LOG(INFO, "BT Discovery disabled: impl=%p", &GetImpl());
}
MutexLock lock(&mutex_);
if (!discovery_enabled_) return true;
discovery_enabled_ = false;
discovery_callback_ = {};
devices_.clear();
NEARBY_LOG(INFO, "BT Discovery disabled: impl=%p", &GetImpl());
return impl_->StopDiscovery();
}
@@ -283,6 +283,11 @@ TEST_F(BluetoothClassicMediumTest, CanListenForService) {
server_socket.Close();
}
TEST_F(BluetoothClassicMediumTest, FailIfDiscovering) {
EXPECT_TRUE(bt_a_->StartDiscovery({}));
EXPECT_FALSE(bt_a_->StartDiscovery({}));
}
} // namespace
} // namespace nearby
} // namespace location