Remove BLE V1 codes

PiperOrigin-RevId: 811369802
This commit is contained in:
Guogang Li
2025-09-25 08:56:51 -07:00
committed by Copybara-Service
parent 72088b7fe2
commit 5fbef9e11e
51 changed files with 200 additions and 4969 deletions
-1
View File
@@ -152,7 +152,6 @@ cc_library(
name = "comm",
hdrs = [
"awdl.h",
"ble.h",
"ble_v2.h",
"bluetooth_adapter.h",
"bluetooth_classic.h",
@@ -308,12 +308,6 @@ void GNCEnsureFileAtPath(std::string path) {
XCTAssertEqual(bluetooth_classic_medium.get(), nullptr);
}
- (void)testCreateBleMedium {
auto bluetooth_adapter = nearby::api::ImplementationPlatform::CreateBluetoothAdapter();
auto ble_medium = nearby::api::ImplementationPlatform::CreateBleMedium(*bluetooth_adapter);
XCTAssertEqual(ble_medium.get(), nullptr);
}
- (void)testCreateBleV2Medium {
auto bluetooth_adapter = nearby::api::ImplementationPlatform::CreateBluetoothAdapter();
auto ble_medium = nearby::api::ImplementationPlatform::CreateBleV2Medium(*bluetooth_adapter);
@@ -172,10 +172,6 @@ std::unique_ptr<BluetoothClassicMedium> ImplementationPlatform::CreateBluetoothC
return nullptr;
}
std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(api::BluetoothAdapter& adapter) {
return nullptr;
}
std::unique_ptr<ble_v2::BleMedium> ImplementationPlatform::CreateBleV2Medium(
api::BluetoothAdapter& adapter) {
return std::make_unique<apple::BleMedium>();
-122
View File
@@ -1,122 +0,0 @@
// 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 PLATFORM_API_BLE_H_
#define PLATFORM_API_BLE_H_
#include "internal/platform/byte_array.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
namespace nearby {
namespace api {
// Opaque wrapper over a BLE peripheral. Must contain enough data about a
// particular BLE device to connect to its GATT server.
class BlePeripheral {
public:
virtual ~BlePeripheral() = default;
virtual std::string GetName() const = 0;
virtual ByteArray GetAdvertisementBytes(
const std::string& service_id) const = 0;
};
class BleSocket {
public:
virtual ~BleSocket() = default;
// Returns the InputStream of the BleSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the BleSocket object is destroyed.
virtual InputStream& GetInputStream() = 0;
// Returns the OutputStream of the BleSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the BleSocket object is destroyed.
virtual OutputStream& GetOutputStream() = 0;
// Conforms to the same contract as
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#close().
//
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
virtual Exception Close() = 0;
// Returns valid BlePeripheral pointer if there is a connection, and
// nullptr otherwise.
virtual BlePeripheral* GetRemotePeripheral() = 0;
};
// Container of operations that can be performed over the BLE medium.
class BleMedium {
public:
virtual ~BleMedium() = default;
virtual bool StartAdvertising(
const std::string& service_id, const ByteArray& advertisement_bytes,
const std::string& fast_advertisement_service_uuid) = 0;
virtual bool StopAdvertising(const std::string& service_id) = 0;
// Callback that is invoked when a discovered peripheral is found or lost.
struct DiscoveredPeripheralCallback {
absl::AnyInvocable<void(BlePeripheral& peripheral,
const std::string& service_id,
bool fast_advertisement)>
peripheral_discovered_cb =
DefaultCallback<BlePeripheral&, const std::string&, bool>();
absl::AnyInvocable<void(BlePeripheral& peripheral,
const std::string& service_id)>
peripheral_lost_cb =
DefaultCallback<BlePeripheral&, const std::string&>();
};
// Returns true once the BLE scan has been initiated.
virtual bool StartScanning(const std::string& service_id,
const std::string& fast_advertisement_service_uuid,
DiscoveredPeripheralCallback callback) = 0;
// Returns true once BLE scanning for service_id is well and truly stopped;
// after this returns, there must be no more invocations of the
// DiscoveredPeripheralCallback passed in to StartScanning() for service_id.
virtual bool StopScanning(const std::string& service_id) = 0;
// Callback that is invoked when a new connection is accepted.
using AcceptedConnectionCallback = absl::AnyInvocable<void(
BleSocket& socket, const std::string& service_id)>;
// Returns true once BLE socket connection requests to service_id can be
// accepted.
virtual bool StartAcceptingConnections(
const std::string& service_id, AcceptedConnectionCallback callback) = 0;
virtual bool StopAcceptingConnections(const std::string& service_id) = 0;
// Connects to a BLE peripheral.
// On success, returns a new BleSocket.
// On error, returns nullptr.
virtual std::unique_ptr<BleSocket> Connect(
BlePeripheral& peripheral, const std::string& service_id,
CancellationFlag* cancellation_flag) = 0;
};
} // namespace api
} // namespace nearby
#endif // PLATFORM_API_BLE_H_
+4 -5
View File
@@ -1,6 +1,3 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,6 +11,10 @@ load("@rules_cc//cc:cc_test.bzl", "cc_test")
# 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.
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")
licenses(["notice"])
cc_library(
@@ -79,7 +80,6 @@ cc_library(
testonly = True,
srcs = [
"awdl.cc",
"ble.cc",
"ble_v2.cc",
"bluetooth_adapter.cc",
"bluetooth_classic.cc",
@@ -90,7 +90,6 @@ cc_library(
],
hdrs = [
"awdl.h",
"ble.h",
"ble_v2.h",
"bluetooth_adapter.h",
"bluetooth_classic.h",
-316
View File
@@ -1,316 +0,0 @@
// 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.
#include "internal/platform/implementation/g3/ble.h"
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/log/check.h"
#include "absl/strings/escaping.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/cancellation_flag_listener.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/g3/bluetooth_adapter.h"
#include "internal/platform/implementation/shared/count_down_latch.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
namespace nearby {
namespace g3 {
BlePeripheral* BleSocket::GetRemotePeripheral() {
absl::MutexLock lock(mutex_);
return peripheral_;
}
std::unique_ptr<api::BleSocket> BleServerSocket::Accept(
BlePeripheral* peripheral) {
absl::MutexLock lock(mutex_);
if (closed_) return {};
while (pending_sockets_.empty()) {
cond_.Wait(&mutex_);
if (closed_) break;
}
if (closed_) return {};
auto* remote_socket =
pending_sockets_.extract(pending_sockets_.begin()).value();
CHECK(remote_socket);
auto local_socket = std::make_unique<BleSocket>(peripheral);
local_socket->Connect(*remote_socket);
remote_socket->Connect(*local_socket);
cond_.SignalAll();
return local_socket;
}
bool BleServerSocket::Connect(BleSocket& socket) {
absl::MutexLock lock(mutex_);
if (closed_) return false;
if (socket.IsConnected()) {
LOG(ERROR) << "Failed to connect to Ble server socket: already connected";
return true; // already connected.
}
// add client socket to the pending list
pending_sockets_.emplace(&socket);
cond_.SignalAll();
while (!socket.IsConnected()) {
cond_.Wait(&mutex_);
if (closed_) return false;
}
return true;
}
void BleServerSocket::SetCloseNotifier(absl::AnyInvocable<void()> notifier) {
absl::MutexLock lock(mutex_);
close_notifier_ = std::move(notifier);
}
BleServerSocket::~BleServerSocket() {
absl::MutexLock lock(mutex_);
DoClose();
}
Exception BleServerSocket::Close() {
absl::MutexLock lock(mutex_);
return DoClose();
}
Exception BleServerSocket::DoClose() {
bool should_notify = !closed_;
closed_ = true;
if (should_notify) {
cond_.SignalAll();
if (close_notifier_) {
auto notifier = std::move(close_notifier_);
mutex_.unlock();
// Notifier may contain calls to public API, and may cause deadlock, if
// mutex_ is held during the call.
notifier();
mutex_.lock();
}
}
return {Exception::kSuccess};
}
BleMedium::BleMedium(api::BluetoothAdapter& adapter)
: adapter_(static_cast<BluetoothAdapter*>(&adapter)) {
adapter_->SetBleMedium(this);
auto& env = MediumEnvironment::Instance();
env.RegisterBleMedium(*this);
}
BleMedium::~BleMedium() {
adapter_->SetBleMedium(nullptr);
auto& env = MediumEnvironment::Instance();
env.UnregisterBleMedium(*this);
StopAdvertising(advertising_info_.service_id);
StopScanning(scanning_info_.service_id);
accept_loops_runner_.Shutdown();
LOG(INFO) << "BleMedium dtor advertising_accept_thread_running_ = "
<< acceptance_thread_running_.load();
// If acceptance thread is still running, wait to finish.
if (acceptance_thread_running_) {
while (acceptance_thread_running_) {
shared::CountDownLatch latch(1);
close_accept_loops_runner_.Execute([&latch]() { latch.CountDown(); });
latch.Await();
}
}
}
bool BleMedium::StartAdvertising(
const std::string& service_id, const ByteArray& advertisement_bytes,
const std::string& fast_advertisement_service_uuid) {
LOG(INFO) << "G3 Ble StartAdvertising: service_id=" << service_id
<< ", advertisement bytes="
<< absl::BytesToHexString(std::string(advertisement_bytes)) << "("
<< advertisement_bytes.size() << "),"
<< ", fast advertisement service uuid="
<< absl::BytesToHexString(fast_advertisement_service_uuid);
auto& env = MediumEnvironment::Instance();
auto& peripheral = adapter_->GetPeripheral();
peripheral.SetAdvertisementBytes(service_id, advertisement_bytes);
bool fast_advertisement = !fast_advertisement_service_uuid.empty();
env.UpdateBleMediumForAdvertising(*this, peripheral, service_id,
fast_advertisement, true);
absl::MutexLock lock(mutex_);
if (server_socket_ != nullptr) server_socket_.release();
server_socket_ = std::make_unique<BleServerSocket>();
acceptance_thread_running_.exchange(true);
accept_loops_runner_.Execute([&env, this, service_id]() mutable {
while (true) {
if (accept_loops_runner_.InShutdown()) break;
auto client_socket =
server_socket_->Accept(&(this->adapter_->GetPeripheral()));
if (client_socket == nullptr) break;
env.CallBleAcceptedConnectionCallback(*this, *(client_socket.release()),
service_id);
}
acceptance_thread_running_.exchange(false);
});
advertising_info_.service_id = service_id;
return true;
}
bool BleMedium::StopAdvertising(const std::string& service_id) {
LOG(INFO) << "G3 Ble StopAdvertising: service_id=" << service_id;
{
absl::MutexLock lock(mutex_);
if (advertising_info_.Empty()) {
LOG(INFO) << "G3 Ble StopAdvertising: Can't stop advertising "
"because we never started advertising.";
return false;
}
advertising_info_.Clear();
}
auto& env = MediumEnvironment::Instance();
env.UpdateBleMediumForAdvertising(*this, adapter_->GetPeripheral(),
service_id, /*fast_advertisement=*/false,
/*enabled=*/false);
accept_loops_runner_.Shutdown();
if (server_socket_ == nullptr) {
LOG(ERROR) << "G3 Ble StopAdvertising: Failed to find Ble Server "
"socket: service_id="
<< service_id;
// Fall through for server socket not found.
return true;
}
if (!server_socket_->Close().Ok()) {
LOG(INFO)
<< "G3 Ble StopAdvertising: Failed to close Ble server socket for "
<< service_id;
return false;
}
return true;
}
bool BleMedium::StartScanning(
const std::string& service_id,
const std::string& fast_advertisement_service_uuid,
DiscoveredPeripheralCallback callback) {
LOG(INFO) << "G3 Ble StartScanning: service_id=" << service_id;
auto& env = MediumEnvironment::Instance();
env.UpdateBleMediumForScanning(*this, service_id,
fast_advertisement_service_uuid,
std::move(callback), true);
{
absl::MutexLock lock(mutex_);
scanning_info_.service_id = service_id;
}
return true;
}
bool BleMedium::StopScanning(const std::string& service_id) {
LOG(INFO) << "G3 Ble StopScanning: service_id=" << service_id;
{
absl::MutexLock lock(mutex_);
if (scanning_info_.Empty()) {
LOG(INFO) << "G3 Ble StopDiscovery: Can't stop scanning because "
"we never started scanning.";
return false;
}
scanning_info_.Clear();
}
auto& env = MediumEnvironment::Instance();
env.UpdateBleMediumForScanning(*this, service_id, {}, {}, false);
return true;
}
bool BleMedium::StartAcceptingConnections(const std::string& service_id,
AcceptedConnectionCallback callback) {
LOG(INFO) << "G3 Ble StartAcceptingConnections: service_id=" << service_id;
auto& env = MediumEnvironment::Instance();
env.UpdateBleMediumForAcceptedConnection(*this, service_id,
std::move(callback));
return true;
}
bool BleMedium::StopAcceptingConnections(const std::string& service_id) {
LOG(INFO) << "G3 Ble StopAcceptingConnections: service_id=" << service_id;
auto& env = MediumEnvironment::Instance();
env.UpdateBleMediumForAcceptedConnection(*this, service_id, {});
return true;
}
std::unique_ptr<api::BleSocket> BleMedium::Connect(
api::BlePeripheral& remote_peripheral, const std::string& service_id,
CancellationFlag* cancellation_flag) {
LOG(INFO) << "G3 Ble Connect [self]: medium=" << this
<< ", adapter=" << &GetAdapter()
<< ", peripheral=" << &GetAdapter().GetPeripheral()
<< ", service_id=" << service_id;
// First, find an instance of remote medium, that exposed this peripheral.
auto& adapter = static_cast<BlePeripheral&>(remote_peripheral).GetAdapter();
auto* medium = static_cast<BleMedium*>(adapter.GetBleMedium());
if (!medium) return {}; // Can't find medium. Bail out.
BleServerSocket* remote_server_socket = nullptr;
LOG(INFO) << "G3 Ble Connect [peer]: medium=" << medium
<< ", adapter=" << &adapter << ", peripheral=" << &remote_peripheral
<< ", service_id=" << service_id;
// Then, find our server socket context in this medium.
{
absl::MutexLock medium_lock(medium->mutex_);
remote_server_socket = medium->server_socket_.get();
if (remote_server_socket == nullptr) {
LOG(ERROR)
<< "G3 Ble Connect: Failed to find Ble Server socket: service_id="
<< service_id;
return {};
}
}
if (cancellation_flag->Cancelled()) {
LOG(ERROR) << "G3 BLE Connect: Has been cancelled: "
"service_id="
<< service_id;
return {};
}
CancellationFlagListener listener(cancellation_flag, [this]() {
LOG(INFO) << "G3 BLE Cancel Connect.";
if (server_socket_ != nullptr) server_socket_->Close();
});
BlePeripheral peripheral = static_cast<BlePeripheral&>(remote_peripheral);
auto socket = std::make_unique<BleSocket>(&peripheral);
// Finally, Request to connect to this socket.
if (!remote_server_socket->Connect(*socket)) {
LOG(ERROR) << "G3 Ble Connect: Failed to connect to existing Ble "
"Server socket: service_id="
<< service_id;
return {};
}
LOG(INFO) << "G3 Ble Connect: connected: socket=" << socket.get();
return socket;
}
} // namespace g3
} // namespace nearby
-198
View File
@@ -1,198 +0,0 @@
// 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 PLATFORM_IMPL_G3_BLE_H_
#define PLATFORM_IMPL_G3_BLE_H_
#include <memory>
#include <string>
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/escaping.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/g3/bluetooth_adapter.h"
#include "internal/platform/implementation/g3/bluetooth_classic.h"
#include "internal/platform/implementation/g3/multi_thread_executor.h"
#include "internal/platform/implementation/g3/socket_base.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
namespace nearby {
namespace g3 {
class BleMedium;
class BleSocket : public api::BleSocket, public SocketBase {
public:
BleSocket() = default;
explicit BleSocket(BlePeripheral* peripheral) : peripheral_(peripheral) {}
// Returns the InputStream of this connected BleSocket.
InputStream& GetInputStream() override {
return SocketBase::GetInputStream();
}
// Returns the OutputStream of this connected BleSocket.
// This stream is for local side to write.
OutputStream& GetOutputStream() override {
return SocketBase::GetOutputStream();
}
// Returns address of a remote BleSocket or nullptr.
BleSocket* GetRemoteSocket() {
return static_cast<BleSocket*>(SocketBase::GetRemoteSocket());
}
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() override { return SocketBase::Close(); }
// Returns valid BlePeripheral pointer if there is a connection, and
// nullptr otherwise.
BlePeripheral* GetRemotePeripheral() override ABSL_LOCKS_EXCLUDED(mutex_);
private:
BlePeripheral* peripheral_;
};
class BleServerSocket {
public:
~BleServerSocket();
// Blocks until either:
// - at least one incoming connection request is available, or
// - ServerSocket is closed.
// On success, returns connected socket, ready to exchange data.
// Returns nullptr on error.
// Once error is reported, it is permanent, and ServerSocket has to be closed.
//
// Called by the server side of a connection.
// Returns BleSocket to the server side.
// If not null, returned socket is connected to its remote (client-side) peer.
std::unique_ptr<api::BleSocket> Accept(BlePeripheral* peripheral)
ABSL_LOCKS_EXCLUDED(mutex_);
// Blocks until either:
// - connection is available, or
// - server socket is closed, or
// - error happens.
//
// Called by the client side of a connection.
// Returns true, if socket is successfully connected.
bool Connect(BleSocket& socket) ABSL_LOCKS_EXCLUDED(mutex_);
// Called by the server side of a connection before passing ownership of
// BleServerSocker to user, to track validity of a pointer to this
// server socket,
void SetCloseNotifier(absl::AnyInvocable<void()> notifier)
ABSL_LOCKS_EXCLUDED(mutex_);
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
// Calls close_notifier if it was previously set, and marks socket as closed.
Exception Close() ABSL_LOCKS_EXCLUDED(mutex_);
private:
Exception DoClose() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
absl::Mutex mutex_;
absl::CondVar cond_;
absl::flat_hash_set<BleSocket*> pending_sockets_ ABSL_GUARDED_BY(mutex_);
absl::AnyInvocable<void()> close_notifier_ ABSL_GUARDED_BY(mutex_);
bool closed_ ABSL_GUARDED_BY(mutex_) = false;
};
// Container of operations that can be performed over the BLE medium.
class BleMedium : public api::BleMedium {
public:
explicit BleMedium(api::BluetoothAdapter& adapter);
~BleMedium() override;
// Returns true once the Ble advertising has been initiated.
bool StartAdvertising(
const std::string& service_id, const ByteArray& advertisement_bytes,
const std::string& fast_advertisement_service_uuid) override
ABSL_LOCKS_EXCLUDED(mutex_);
bool StopAdvertising(const std::string& service_id) override
ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true once the Ble scanning has been initiated.
bool StartScanning(const std::string& service_id,
const std::string& fast_advertisement_service_uuid,
DiscoveredPeripheralCallback callback) override
ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true once Ble scanning for service_id is well and truly
// stopped; after this returns, there must be no more invocations of the
// DiscoveredPeripheralCallback passed in to StartScanning() for service_id.
bool StopScanning(const std::string& service_id) override
ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true once Ble socket connection requests to service_id can be
// accepted.
bool StartAcceptingConnections(const std::string& service_id,
AcceptedConnectionCallback callback) override
ABSL_LOCKS_EXCLUDED(mutex_);
bool StopAcceptingConnections(const std::string& service_id) override
ABSL_LOCKS_EXCLUDED(mutex_);
// Connects to existing remote Ble peripheral.
//
// On success, returns a new BleSocket.
// On error, returns nullptr.
std::unique_ptr<api::BleSocket> Connect(
api::BlePeripheral& remote_peripheral, const std::string& service_id,
CancellationFlag* cancellation_flag) override ABSL_LOCKS_EXCLUDED(mutex_);
BluetoothAdapter& GetAdapter() { return *adapter_; }
private:
static constexpr int kMaxConcurrentAcceptLoops = 5;
struct AdvertisingInfo {
bool Empty() const { return service_id.empty(); }
void Clear() { service_id.clear(); }
std::string service_id;
};
struct ScanningInfo {
bool Empty() const { return service_id.empty(); }
void Clear() { service_id.clear(); }
std::string service_id;
};
absl::Mutex mutex_;
BluetoothAdapter* adapter_; // Our device adapter; read-only.
// A thread pool dedicated to running all the accept loops from
// StartAdvertising().
MultiThreadExecutor accept_loops_runner_{kMaxConcurrentAcceptLoops};
std::atomic_bool acceptance_thread_running_ = false;
// A thread pool dedicated to wait to complete the accept_loops_runner_.
MultiThreadExecutor close_accept_loops_runner_{1};
// A server socket is established when start advertising.
std::unique_ptr<BleServerSocket> server_socket_;
AdvertisingInfo advertising_info_ ABSL_GUARDED_BY(mutex_);
ScanningInfo scanning_info_ ABSL_GUARDED_BY(mutex_);
};
} // namespace g3
} // namespace nearby
#endif // PLATFORM_IMPL_G3_BLE_H_
@@ -14,9 +14,14 @@
#include "internal/platform/implementation/g3/bluetooth_adapter.h"
#include <cstdint>
#include <string>
#include <utility>
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/mac_address.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/prng.h"
@@ -27,22 +32,6 @@ namespace {
constexpr std::uint64_t kMacAddressMask = 0x0000FFFFFFFFFFFF;
}
BlePeripheral::BlePeripheral(BluetoothAdapter* adapter) : adapter_(*adapter) {}
std::string BlePeripheral::GetName() const {
return adapter_.GetAddress().ToString();
}
ByteArray BlePeripheral::GetAdvertisementBytes(
const std::string& service_id) const {
return advertisement_bytes_;
}
void BlePeripheral::SetAdvertisementBytes(
const std::string& service_id, const ByteArray& advertisement_bytes) {
advertisement_bytes_ = advertisement_bytes;
}
BluetoothDevice::BluetoothDevice(BluetoothAdapter* adapter)
: adapter_(*adapter) {}
@@ -52,9 +41,7 @@ std::string BluetoothDevice::GetMacAddress() const {
return GetAddress().ToString();
}
MacAddress BluetoothDevice::GetAddress() const {
return adapter_.GetAddress();
}
MacAddress BluetoothDevice::GetAddress() const { return adapter_.GetAddress(); }
BluetoothAdapter::BluetoothAdapter() {
std::uint64_t raw_mac_addr = Prng().NextInt64() & kMacAddressMask;
@@ -73,10 +60,6 @@ void BluetoothAdapter::SetBluetoothClassicMedium(
bluetooth_classic_medium_ = medium;
}
void BluetoothAdapter::SetBleMedium(api::BleMedium* medium) {
ble_medium_ = medium;
}
void BluetoothAdapter::SetBleV2Medium(api::ble_v2::BleMedium* medium) {
ble_v2_medium_ = medium;
}
@@ -21,7 +21,6 @@
#include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/bluetooth_classic.h"
@@ -33,28 +32,6 @@ namespace g3 {
// BluetoothDevice and BluetoothAdapter have a mutual dependency.
class BluetoothAdapter;
// Opaque wrapper over a Ble peripheral. Must contain enough data about a
// particular Ble device to connect to its GATT server.
class BlePeripheral : public api::BlePeripheral {
public:
~BlePeripheral() override = default;
std::string GetName() const override;
ByteArray GetAdvertisementBytes(const std::string& service_id) const override;
void SetAdvertisementBytes(const std::string& service_id,
const ByteArray& advertisement_bytes);
BluetoothAdapter& GetAdapter() { return adapter_; }
private:
// Only BluetoothAdapter may instantiate BlePeripheral.
friend class BluetoothAdapter;
explicit BlePeripheral(BluetoothAdapter* adapter);
BluetoothAdapter& adapter_;
ByteArray advertisement_bytes_;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
class BluetoothDevice : public api::BluetoothDevice {
public:
@@ -121,11 +98,6 @@ class BluetoothAdapter : public api::BluetoothAdapter {
return bluetooth_classic_medium_;
}
BlePeripheral& GetPeripheral() { return peripheral_; }
void SetBleMedium(api::BleMedium* medium);
api::BleMedium* GetBleMedium() { return ble_medium_; }
void SetBleV2Medium(api::ble_v2::BleMedium* medium);
api::ble_v2::BleMedium* GetBleV2Medium() { return ble_v2_medium_; }
@@ -138,9 +110,7 @@ class BluetoothAdapter : public api::BluetoothAdapter {
private:
mutable absl::Mutex mutex_;
BluetoothDevice device_{this};
BlePeripheral peripheral_{this};
api::BluetoothClassicMedium* bluetooth_classic_medium_ = nullptr;
api::BleMedium* ble_medium_ = nullptr;
api::ble_v2::BleMedium* ble_v2_medium_ = nullptr;
MacAddress mac_address_;
ScanMode mode_ ABSL_GUARDED_BY(mutex_) = ScanMode::kNone;
@@ -29,7 +29,6 @@
#include "internal/platform/implementation/atomic_boolean.h"
#include "internal/platform/implementation/atomic_reference.h"
#include "internal/platform/implementation/awdl.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/bluetooth_classic.h"
@@ -62,7 +61,6 @@
#endif
#include "internal/platform/implementation/g3/atomic_boolean.h"
#include "internal/platform/implementation/g3/atomic_reference.h"
#include "internal/platform/implementation/g3/ble.h"
#include "internal/platform/implementation/g3/ble_v2.h"
#include "internal/platform/implementation/g3/bluetooth_adapter.h"
#include "internal/platform/implementation/g3/bluetooth_classic.h"
@@ -187,11 +185,6 @@ ImplementationPlatform::CreateBluetoothClassicMedium(
return std::make_unique<g3::BluetoothClassicMedium>(adapter);
}
std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(
api::BluetoothAdapter& adapter) {
return std::make_unique<g3::BleMedium>(adapter);
}
std::unique_ptr<api::ble_v2::BleMedium>
ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter& adapter) {
return std::make_unique<g3::BleV2Medium>(
+1 -3
View File
@@ -21,10 +21,9 @@
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/awdl.h"
#include "internal/platform/implementation/atomic_boolean.h"
#include "internal/platform/implementation/atomic_reference.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/awdl.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/bluetooth_classic.h"
@@ -131,7 +130,6 @@ class ImplementationPlatform {
static std::unique_ptr<BluetoothAdapter> CreateBluetoothAdapter();
static std::unique_ptr<BluetoothClassicMedium> CreateBluetoothClassicMedium(
BluetoothAdapter&);
static std::unique_ptr<BleMedium> CreateBleMedium(BluetoothAdapter&);
static std::unique_ptr<api::ble_v2::BleMedium> CreateBleV2Medium(
api::BluetoothAdapter&);
static std::unique_ptr<api::CredentialStorage> CreateCredentialStorage();
@@ -101,12 +101,8 @@ cc_library(
cc_library(
name = "comm",
hdrs = [
"ble.h",
"ble_gatt_client.h",
"ble_gatt_server.h",
"ble_medium.h",
"ble_peripheral.h",
"ble_socket.h",
"ble_v2.h",
"ble_v2_server_socket.h",
"ble_v2_socket.h",
@@ -208,8 +204,6 @@ cc_library(
srcs = [
"ble_gatt_client.cc",
"ble_gatt_server.cc",
"ble_medium.cc",
"ble_socket.cc",
"ble_v2.cc",
"ble_v2_server_socket.cc",
"ble_v2_socket.cc",
@@ -341,7 +335,6 @@ cc_test(
"atomic_boolean_test.cc",
"atomic_reference_test.cc",
"ble_gatt_server_test.cc",
"ble_medium_test.cc",
"ble_v2_test.cc",
"bluetooth_adapter_test.cc",
"count_down_latch_test.cc",
@@ -1,22 +0,0 @@
// Copyright 2022 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 PLATFORM_IMPL_WINDOWS_BLE_H_
#define PLATFORM_IMPL_WINDOWS_BLE_H_
#include "internal/platform/implementation/windows/ble_peripheral.h"
#include "internal/platform/implementation/windows/ble_medium.h"
#include "internal/platform/implementation/windows/ble_socket.h"
#endif // PLATFORM_IMPL_WINDOWS_BLE_H_
@@ -1,651 +0,0 @@
// Copyright 2022 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.
#include "internal/platform/implementation/windows/ble_medium.h"
#include <chrono> // NOLINT
#include <cstdint>
#include <exception>
#include <future> // NOLINT
#include <list>
#include <memory>
#include <string>
#include <utility>
#include "absl/strings/escaping.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/mac_address.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/windows/ble_peripheral.h"
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
#include "internal/platform/logging.h"
#include "winrt/Windows.Devices.Bluetooth.Advertisement.h"
#include "winrt/Windows.Devices.Bluetooth.h"
#include "winrt/Windows.Foundation.Collections.h"
#include "winrt/Windows.Storage.Streams.h"
#include "winrt/base.h"
namespace nearby {
namespace windows {
namespace {
// Specifies common Bluetooth error cases.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetootherror?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::BluetoothError;
// Represents a Bluetooth LE advertisement payload.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisement?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisement;
// Represents a Bluetooth LE advertisement section. A Bluetooth LE advertisement
// packet can contain multiple instances of these
// BluetoothLEAdvertisementDataSection objects.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementdatasection?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementDataSection;
// Represents the Bluetooth LE advertisement types defined in the Generic Access
// Profile (GAP) by the Bluetooth Special Interest Group (SIG).
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementdatatypes?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementDataTypes;
// Represents an object to send Bluetooth Low Energy (LE) advertisements.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementpublisher?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementPublisher;
// Represents the possible states of the BluetoothLEAdvertisementPublisher.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementpublisherstatus?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementPublisherStatus;
// Provides data for a StatusChanged event on a
// BluetoothLEAdvertisementPublisher.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementpublisherstatuschangedeventargs?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementPublisherStatusChangedEventArgs;
// BluetoothLEAdvertisement
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisement?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisement;
// Provides data for a Received event on a BluetoothLEAdvertisementWatcher. A
// BluetoothLEAdvertisementReceivedEventArgs instance is created when the
// Received event occurs on a BluetoothLEAdvertisementWatcher object.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementreceivedeventargs?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementReceivedEventArgs;
// Represents an object to receive Bluetooth Low Energy (LE) advertisements.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementwatcher?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementWatcher;
// Represents the possible states of the BluetoothLEAdvertisementWatcher.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementwatcherstatus?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementWatcherStatus;
// Provides data for a Stopped event on a BluetoothLEAdvertisementWatcher. A
// BluetoothLEAdvertisementWatcherStoppedEventArgs instance is created when the
// Stopped event occurs on a BluetoothLEAdvertisementWatcher object.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementwatcherstoppedeventargs?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementWatcherStoppedEventArgs;
// Defines constants that specify a Bluetooth LE scanning mode.
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothlescanningmode?view=winrt-22621
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEScanningMode;
// Reads data from an input stream.
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-22621
using ::winrt::Windows::Storage::Streams::DataReader;
// Writes data to an output stream.
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-22621
using ::winrt::Windows::Storage::Streams::DataWriter;
// Represents a time interval as a signed 64-bit integer value.
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.timespan?view=winrt-22621
using ::winrt::Windows::Foundation::TimeSpan;
template <typename T>
using IVector = winrt::Windows::Foundation::Collections::IVector<T>;
// Copresence Service UUID 0xfef3 (little-endian)
constexpr uint16_t kCopresenceServiceUuid = 0xf3fe;
bool IsFastPairScanner() {
return FeatureFlags::GetInstance()
.GetFlags()
.enable_scan_for_fast_pair_advertisement;
}
} // namespace
BleMedium::BleMedium(api::BluetoothAdapter& adapter)
: adapter_(static_cast<BluetoothAdapter*>(&adapter)) {}
bool BleMedium::StartAdvertising(
const std::string& service_id, const ByteArray& advertisement_bytes,
const std::string& fast_advertisement_service_uuid) {
try {
if (!adapter_->IsEnabled()) {
LOG(WARNING) << "BLE cannot start advertising because the "
"bluetooth adapter is not enabled.";
return false;
}
LOG(INFO) << "Windows Ble StartAdvertising: service_id=" << service_id
<< ", advertisement bytes= 0x"
<< absl::BytesToHexString(advertisement_bytes.AsStringView())
<< "(" << advertisement_bytes.size() << "),"
<< " fast advertisement service uuid= 0x"
<< absl::BytesToHexString(fast_advertisement_service_uuid);
if (is_publisher_started_) {
LOG(WARNING) << "BLE cannot start to advertise again when it is running.";
return false;
}
DataWriter data_writer;
// TODO(b/234229562): Add parsing logic for fast_advertisement_service_uuid
// and insert into the 0x16 Service Data field in the BLE advertisement when
// Fast Advertisement is enabled. For Extended Advertising, use the same
// hardcoded Copresence service uuid 0xFEF3.
// Copresence Service UUID 0xfef3 (little-endian)
data_writer.WriteUInt16(kCopresenceServiceUuid);
for (int i = 0; i < advertisement_bytes.size(); ++i) {
data_writer.WriteByte(
static_cast<uint8_t>(*(advertisement_bytes.data() + i)));
}
BluetoothLEAdvertisementDataSection service_data =
BluetoothLEAdvertisementDataSection(0x16, data_writer.DetachBuffer());
BluetoothLEAdvertisement advertisement;
IVector<BluetoothLEAdvertisementDataSection> data_sections =
advertisement.DataSections();
data_sections.Append(service_data);
advertisement.DataSections() = data_sections;
// Use Extended Advertising if Fast Advertisement Service Uuid is empty
// string because the long format advertisement will be used
if (adapter_->IsExtendedAdvertisingSupported() &&
fast_advertisement_service_uuid.empty()) {
publisher_ = BluetoothLEAdvertisementPublisher(advertisement);
publisher_.UseExtendedAdvertisement(true);
} else {
// Extended Advertisement not supported, must make sure
// advertisement_bytes is less than 27 bytes
if (advertisement_bytes.size() <= 27) {
publisher_ = BluetoothLEAdvertisementPublisher(advertisement);
publisher_.UseExtendedAdvertisement(false);
} else {
// otherwise no-op
LOG(INFO) << "Everyone Mode unavailable for hardware that does "
"not support Extended Advertising.";
publisher_ = nullptr;
return false;
}
}
publisher_token_ =
publisher_.StatusChanged({this, &BleMedium::PublisherHandler});
publisher_.Start();
is_publisher_started_ = true;
LOG(INFO) << "Windows Ble StartAdvertising started.";
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__
<< ": Exception to start BLE advertising: " << exception.what();
return false;
} catch (const winrt::hresult_error& ex) {
LOG(ERROR) << __func__
<< ": Exception to start BLE advertising: " << ex.code() << ": "
<< winrt::to_string(ex.message());
return false;
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exception.";
return false;
}
}
bool BleMedium::StopAdvertising(const std::string& service_id) {
try {
if (!adapter_->IsEnabled()) {
LOG(WARNING) << "BLE cannot stop advertising because the "
"bluetooth adapter is not enabled.";
return false;
}
LOG(INFO) << "Windows Ble StopAdvertising: service_id=" << service_id;
if (!is_publisher_started_) {
LOG(WARNING) << "BLE advertising is not running.";
return false;
}
// publisher_ may be null when status changed during advertising.
if (publisher_ != nullptr &&
publisher_.Status() ==
BluetoothLEAdvertisementPublisherStatus::Started) {
publisher_.Stop();
}
// Don't need to wait for the status becomes to `Stopped`. If application
// starts to scanning immediately, the scanning still needs to wait the
// stopping to finish.
is_publisher_started_ = false;
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__
<< ": Exception to stop BLE advertising: " << exception.what();
return false;
} catch (const winrt::hresult_error& ex) {
LOG(ERROR) << __func__
<< ": Exception to stop BLE advertising: " << ex.code() << ": "
<< winrt::to_string(ex.message());
return false;
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exception.";
return false;
}
}
bool BleMedium::StartScanning(
const std::string& service_id,
const std::string& fast_advertisement_service_uuid,
DiscoveredPeripheralCallback callback) {
try {
if (!adapter_->IsEnabled()) {
LOG(WARNING) << "BLE cannot start scanning because the "
"bluetooth adapter is not enabled.";
return false;
}
LOG(INFO) << "Windows Ble StartScanning: service_id=" << service_id;
if (is_watcher_started_) {
LOG(WARNING) << "BLE cannot start to scan again when it is running.";
return false;
}
service_id_ = service_id;
advertisement_received_callback_ = std::move(callback);
{
absl::MutexLock lock(&peripheral_map_mutex_);
peripheral_map_.clear();
lost_peripherals_.clear();
}
watcher_ = BluetoothLEAdvertisementWatcher();
watcher_token_ = watcher_.Stopped({this, &BleMedium::WatcherHandler});
advertisement_received_token_ =
watcher_.Received({this, &BleMedium::AdvertisementReceivedHandler});
if (adapter_->IsExtendedAdvertisingSupported()) {
watcher_.AllowExtendedAdvertisements(true);
}
// Active mode indicates that scan request packets will be sent to query
// for Scan Response
watcher_.ScanningMode(BluetoothLEScanningMode::Active);
::winrt::Windows::Devices::Bluetooth::BluetoothSignalStrengthFilter filter;
filter.SamplingInterval(TimeSpan(std::chrono::seconds(2)));
watcher_.SignalStrengthFilter(filter);
watcher_.Start();
is_watcher_started_ = true;
LOG(INFO) << "Windows Ble StartScanning started.";
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__
<< ": Exception to start BLE scanning: " << exception.what();
return false;
} catch (const winrt::hresult_error& ex) {
LOG(ERROR) << __func__ << ": Exception to start BLE scanning: " << ex.code()
<< ": " << winrt::to_string(ex.message());
return false;
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exception.";
return false;
}
}
bool BleMedium::StopScanning(const std::string& service_id) {
try {
if (!adapter_->IsEnabled()) {
LOG(WARNING) << "BLE cannot stop scanning because the "
"bluetooth adapter is not enabled.";
return false;
}
LOG(INFO) << "Windows Ble StopScanning: service_id=" << service_id;
if (!is_watcher_started_) {
LOG(WARNING) << "BLE scanning is not running.";
return false;
}
watcher_.Stop();
// Don't need to wait for the status becomes to `Stopped`. If application
// starts to scanning immediately, the scanning still needs to wait the
// stopping to finish.
is_watcher_started_ = false;
LOG(ERROR) << "Windows Ble stoped scanning successfully for service_id="
<< service_id;
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__
<< ": Exception to stop BLE scanning: " << exception.what();
return false;
} catch (const winrt::hresult_error& ex) {
LOG(ERROR) << __func__ << ": Exception to stop BLE scanning: " << ex.code()
<< ": " << winrt::to_string(ex.message());
return false;
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exception.";
return false;
}
}
bool BleMedium::StartAcceptingConnections(const std::string& service_id,
AcceptedConnectionCallback callback) {
LOG(INFO) << "Windows Ble StartAcceptingConnections: service_id="
<< service_id;
return true;
}
bool BleMedium::StopAcceptingConnections(const std::string& service_id) {
LOG(INFO) << "Windows Ble StopAcceptingConnections: service_id="
<< service_id;
return true;
}
std::unique_ptr<api::BleSocket> BleMedium::Connect(
api::BlePeripheral& remote_peripheral, const std::string& service_id,
CancellationFlag* cancellation_flag) {
if (cancellation_flag->Cancelled()) {
LOG(ERROR) << "Windows BLE Connect: Has been cancelled: "
"service_id="
<< service_id;
return {};
}
LOG(ERROR) << "Windows Ble Connect: Cannot connect over BLE socket. "
"service_id="
<< service_id;
return {};
}
void BleMedium::PublisherHandler(
BluetoothLEAdvertisementPublisher publisher,
BluetoothLEAdvertisementPublisherStatusChangedEventArgs args) {
// This method is called when publisher's status is changed.
switch (args.Status()) {
case BluetoothLEAdvertisementPublisherStatus::Created:
LOG(INFO) << "Nearby BLE Medium created to advertise.";
return;
case BluetoothLEAdvertisementPublisherStatus::Started:
LOG(INFO) << "Nearby BLE Medium started to advertise.";
return;
case BluetoothLEAdvertisementPublisherStatus::Stopping:
LOG(INFO) << "Nearby BLE Medium is stopping.";
return;
case BluetoothLEAdvertisementPublisherStatus::Waiting:
LOG(INFO) << "Nearby BLE Medium is waiting.";
return;
case BluetoothLEAdvertisementPublisherStatus::Stopped:
LOG(INFO) << "Nearby BLE Medium stopped to advertise.";
break;
case BluetoothLEAdvertisementPublisherStatus::Aborted:
switch (args.Error()) {
case BluetoothError::Success:
if (publisher_.Status() ==
BluetoothLEAdvertisementPublisherStatus::Started) {
LOG(ERROR) << "Nearby BLE Medium start advertising operation was "
"successfully completed or serviced.";
}
if (publisher_.Status() ==
BluetoothLEAdvertisementPublisherStatus::Stopped) {
LOG(ERROR) << "Nearby BLE Medium stop advertising operation was "
"successfully completed or serviced.";
} else {
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"unknown errors.";
}
break;
case BluetoothError::RadioNotAvailable:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"radio not available.";
break;
case BluetoothError::ResourceInUse:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"resource in use.";
break;
case BluetoothError::DeviceNotConnected:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"remote device is not connected.";
break;
case BluetoothError::DisabledByPolicy:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"disabled by policy.";
break;
case BluetoothError::DisabledByUser:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"disabled by user.";
break;
case BluetoothError::NotSupported:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"hardware not supported.";
break;
case BluetoothError::TransportNotSupported:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"transport not supported.";
break;
case BluetoothError::ConsentRequired:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"consent required.";
break;
case BluetoothError::OtherError:
default:
LOG(ERROR) << "Nearby BLE Medium advertising failed due to "
"unknown errors.";
break;
}
break;
default:
break;
}
// The publisher is stopped. Clean up the running publisher
if (publisher_ != nullptr) {
LOG(ERROR) << "Nearby BLE Medium cleaned the publisher.";
publisher_.StatusChanged(publisher_token_);
publisher_ = nullptr;
is_publisher_started_ = false;
}
}
void BleMedium::WatcherHandler(
BluetoothLEAdvertisementWatcher watcher,
BluetoothLEAdvertisementWatcherStoppedEventArgs args) {
// This method is called when watcher stopped. Args give more detailed
// information on the reason.
switch (args.Error()) {
case BluetoothError::Success:
LOG(ERROR) << "Nearby BLE Medium stoped to scan successfully.";
break;
case BluetoothError::RadioNotAvailable:
LOG(ERROR)
<< "Nearby BLE Medium stoped to scan due to radio not available.";
break;
case BluetoothError::ResourceInUse:
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to resource in use.";
break;
case BluetoothError::DeviceNotConnected:
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to "
"remote device is not connected.";
break;
case BluetoothError::DisabledByPolicy:
LOG(ERROR)
<< "Nearby BLE Medium stoped to scan due to disabled by policy.";
break;
case BluetoothError::DisabledByUser:
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to disabled by user.";
break;
case BluetoothError::NotSupported:
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to "
"hardware not supported.";
break;
case BluetoothError::TransportNotSupported:
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to "
"transport not supported.";
break;
case BluetoothError::ConsentRequired:
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to consent required.";
break;
case BluetoothError::OtherError:
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to unknown errors.";
break;
default:
LOG(ERROR) << "Nearby BLE Medium stoped to scan due to unknown errors.";
break;
}
// No matter the reason, I should clean up the watcher if it is not empty.
// The BLE V1 interface doesn't have an API to return the error to the upper
// layer.
if (watcher_ != nullptr) {
LOG(ERROR) << "Nearby BLE Medium cleaned the watcher.";
watcher_.Stopped(watcher_token_);
watcher_.Received(advertisement_received_token_);
watcher_ = nullptr;
is_watcher_started_ = false;
}
}
void BleMedium::AdvertisementReceivedHandler(
BluetoothLEAdvertisementWatcher watcher,
BluetoothLEAdvertisementReceivedEventArgs args) {
// Handle all BLE advertisements and determine whether the BLE Medium
// Advertisement Scan Response packet (containing Copresence UUID 0xFEF3 in
// 0x16 Service Data) has been received in the handler
BluetoothLEAdvertisement advertisement = args.Advertisement();
for (BluetoothLEAdvertisementDataSection service_data :
advertisement.GetSectionsByType(0x16)) {
// Parse Advertisement Data for Section 0x16 (Service Data)
DataReader data_reader = DataReader::FromBuffer(service_data.Data());
// Discard the first 2 bytes of Service Uuid in Service Data
uint8_t first_byte = data_reader.ReadByte();
uint8_t second_byte = data_reader.ReadByte();
if ((IsFastPairScanner() && first_byte == 0x2c && second_byte == 0xfe) ||
(!IsFastPairScanner() && first_byte == 0xf3 && second_byte == 0xfe)) {
std::string data;
uint8_t unconsumed_buffer_length = data_reader.UnconsumedBufferLength();
for (int i = 0; i < unconsumed_buffer_length; i++) {
data.append(1, static_cast<unsigned char>(data_reader.ReadByte()));
}
ByteArray advertisement_data(data);
VLOG(1) << "Nearby BLE Medium Advertisement discovered. "
"0x16 Service data: advertisement bytes= 0x"
<< absl::BytesToHexString(advertisement_data.AsStringView())
<< "(" << advertisement_data.size() << ")";
MacAddress mac_address;
MacAddress::FromUint64(args.BluetoothAddress(), mac_address);
std::string peripheral_name = mac_address.ToString();
BlePeripheral* peripheral_ptr = nullptr;
{
absl::MutexLock lock(&peripheral_map_mutex_);
if (peripheral_map_.contains(peripheral_name)) {
if (peripheral_map_[peripheral_name]->GetAdvertisementBytes(
service_id_) != advertisement_data) {
LOG(INFO) << "BLE reports lost device: " << peripheral_name;
// Lost the device first and then the report discovered the
// device.
advertisement_received_callback_.peripheral_lost_cb(
/*ble_peripheral*/ *peripheral_map_[peripheral_name],
/*service_id*/ service_id_);
// put the lost peripheral in the lost peripheral list.
lost_peripherals_.push_back(
std::move(peripheral_map_[peripheral_name]));
} else {
// The device is already reported to discover, so don't need to
// call it again.
return;
}
}
auto peripheral = std::make_unique<BlePeripheral>();
peripheral->SetName(peripheral_name);
peripheral->SetAdvertisementBytes(advertisement_data);
peripheral_map_[peripheral_name] = std::move(peripheral);
peripheral_ptr = peripheral_map_[peripheral_name].get();
}
// Received Fast Advertisement packet
if (unconsumed_buffer_length <= 27) {
LOG(INFO) << "Sending Fast Advertisement packet for processing.";
advertisement_received_callback_.peripheral_discovered_cb(
/*ble_peripheral*/ *peripheral_ptr, /*service_id*/ service_id_,
/*is_fast_advertisement*/ true);
} else {
// Received Extended Advertising packet
LOG(INFO) << "Sending Extended Advertising packet for processing.";
advertisement_received_callback_.peripheral_discovered_cb(
/*ble_peripheral*/ *peripheral_ptr, /*service_id*/ service_id_,
/*is_fast_advertisement*/ false);
}
}
}
}
} // namespace windows
} // namespace nearby
@@ -1,129 +0,0 @@
// Copyright 2022 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 THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_MEDIUM_H_
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_MEDIUM_H_
#include <guiddef.h>
#include <future> // NOLINT
#include <list>
#include <memory>
#include <string>
#include <utility>
#include "absl/container/flat_hash_map.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/windows/ble.h"
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
#include "winrt/Windows.Devices.Bluetooth.Advertisement.h"
namespace nearby {
namespace windows {
// Only Fast Advertisement is supported where the remote device's static
// bluetooth MAC address is resolved from Nearby Share Contact certificates
// using salt and encrypted_metadata_key from the BLE advertisement packet.
// The MAC address is then used directly to establish a Bluetooth Classic
// RFCOMM socket.
// Container of operations that can be performed over the BLE medium.
class BleMedium : public api::BleMedium {
public:
explicit BleMedium(api::BluetoothAdapter& adapter);
~BleMedium() override = default;
bool StartAdvertising(
const std::string& service_id, const ByteArray& advertisement_bytes,
const std::string& fast_advertisement_service_uuid) override;
bool StopAdvertising(const std::string& service_id) override;
// Returns true once the BLE scan has been initiated.
bool StartScanning(const std::string& service_id,
const std::string& fast_advertisement_service_uuid,
DiscoveredPeripheralCallback callback) override;
// Returns true once BLE scanning for service_id is well and truly stopped;
// after this returns, there must be no more invocations of the
// DiscoveredPeripheralCallback passed in to StartScanning() for service_id.
bool StopScanning(const std::string& service_id) override;
// Returns true once BLE socket connection requests to service_id can be
// accepted.
bool StartAcceptingConnections(const std::string& service_id,
AcceptedConnectionCallback callback) override;
bool StopAcceptingConnections(const std::string& service_id) override;
// Connects to a BLE peripheral.
// On success, returns a new BleSocket.
// On error, returns nullptr.
std::unique_ptr<api::BleSocket> Connect(api::BlePeripheral& peripheral,
const std::string& service_id,
CancellationFlag* cancellation_flag);
private:
void PublisherHandler(
::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementPublisher publisher,
::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementPublisherStatusChangedEventArgs args);
void AdvertisementReceivedHandler(
::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementWatcher watcher,
::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementReceivedEventArgs args);
void WatcherHandler(::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementWatcher watcher,
::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementWatcherStoppedEventArgs args);
BluetoothAdapter* adapter_;
std::string service_id_;
DiscoveredPeripheralCallback advertisement_received_callback_;
// Map to protect the pointer for BlePeripheral because
// DiscoveredPeripheralCallback only keeps the pointer to the object
absl::Mutex peripheral_map_mutex_;
absl::flat_hash_map<std::string, std::unique_ptr<BlePeripheral>>
peripheral_map_ ABSL_GUARDED_BY(peripheral_map_mutex_);
// The platform implementation will reference lost peripheral in another
// thread after report loss, so we still need to keep the peripheral to
// avoid potential memory issues.
std::list<std::unique_ptr<BlePeripheral>> lost_peripherals_
ABSL_GUARDED_BY(peripheral_map_mutex_);
// WinRT objects
::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementPublisher publisher_ = nullptr;
::winrt::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementWatcher watcher_ = nullptr;
bool is_publisher_started_ = false;
bool is_watcher_started_ = false;
::winrt::event_token publisher_token_;
::winrt::event_token watcher_token_;
::winrt::event_token advertisement_received_token_;
};
} // namespace windows
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_MEDIUM_H_
@@ -1,302 +0,0 @@
// Copyright 2022 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.
#include "internal/platform/implementation/windows/ble_medium.h"
#include <array>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/synchronization/notification.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/windows/ble.h"
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
namespace nearby {
namespace windows {
namespace {
constexpr uint8_t kVersionBitmask = 0xE0;
constexpr uint8_t kSocketVersionBitmask = 0x1C;
constexpr uint8_t kFastAdvertisementFlagBitmask = 0x02;
constexpr uint8_t kPcpBitmask = 0x1F;
constexpr uint8_t kVisibilityBitmask = 0x01;
TEST(BleMedium, DISABLED_StartAdvertising_FastAdvertisement) {
BluetoothAdapter bluetoothAdapter;
BleMedium ble_medium(bluetoothAdapter);
std::array<char, 27> advertising_data_byte_array;
// (1 byte) version [3-bits] + socket_version [3-bits] +
// fast_advertisement_flag [1-bit] + reserved [1-bit]
uint8_t ble_medium_version = 0x02; // mediums::BleAdvertisement::Version::kV2
uint8_t socket_version =
0x02; // mediums::BleAdvertisement::SocketVersion::kV2
bool fast_advertisement = true; // Is Fast Advertisement
uint8_t ble_medium_advertisement_metadata_byte =
(ble_medium_version << 5) & kVersionBitmask;
ble_medium_advertisement_metadata_byte |=
(socket_version << 2) & kSocketVersionBitmask;
ble_medium_advertisement_metadata_byte |=
((fast_advertisement ? 1 : 0) << 1) & kFastAdvertisementFlagBitmask;
advertising_data_byte_array.at(0) =
static_cast<unsigned char>(ble_medium_advertisement_metadata_byte);
// (1 byte) body_length
advertising_data_byte_array.at(1) = static_cast<unsigned char>(
0x17); // always 23 bytes for Fast Advertisement
// (1 byte) Nearby Connection version [3-bits] + pcp [5-bits]
uint8_t ble_connections_version =
0x01; // connections::BleAdvertisement::Version::kV1
uint8_t pcp = 0x02; // connections::Pcp::kP2pCluster
uint8_t ble_connections_advertisement_metadata_byte =
(ble_connections_version << 5) & kVersionBitmask;
ble_connections_advertisement_metadata_byte |= pcp & kPcpBitmask;
advertising_data_byte_array.at(2) =
static_cast<unsigned char>(ble_connections_advertisement_metadata_byte);
// (4 bytes) endpoint_id
for (int i = 0; i < 4; ++i) {
advertising_data_byte_array.at(3 + i) = static_cast<unsigned char>(0x00);
}
// (1 byte) endpoint_info_size
advertising_data_byte_array.at(7) = static_cast<unsigned char>(
0x11); // always 17-bytes for Fast Advertisement
// =========endpoint_info [17-bytes]============
// (1 byte) Nearby Share version [3-bits] + visibility [1-bit] + reserved
// [4-bits]
uint8_t nearby_share_version = 0x00; // nearby share v1
uint8_t visibility = 0x00; // [placeholder] sharing::Visibility::kAllContacts
uint8_t nearby_share_metadata_byte =
(nearby_share_version << 5) & kVersionBitmask;
nearby_share_metadata_byte |= ((visibility & kVisibilityBitmask) << 4);
advertising_data_byte_array.at(8) = static_cast<unsigned char>(0x00);
// (2 bytes) salt
for (int i = 0; i < 2; ++i) {
advertising_data_byte_array.at(9 + i) = static_cast<unsigned char>(0x00);
}
// (14 bytes) encrypted_metadata_key
for (int i = 0; i < 14; ++i) {
advertising_data_byte_array.at(11 + i) = static_cast<unsigned char>(0x00);
}
// =========endpoint_info [17-bytes]============
// (2 bytes) device_token
for (int i = 0; i < 2; ++i) {
advertising_data_byte_array.at(25 + i) = static_cast<unsigned char>(0x00);
}
ByteArray advertising_data(advertising_data_byte_array);
EXPECT_TRUE(
ble_medium.StartAdvertising("NearbyShare", advertising_data, "\xfe\xf3"));
}
TEST(BleMedium, DISABLED_StartAdvertising_ExtendedAdvertising) {
BluetoothAdapter bluetoothAdapter;
BleMedium ble_medium(bluetoothAdapter);
std::array<char, 167> advertising_data_byte_array;
// (1 byte) version [3-bits] + socket_version [3-bits] +
// fast_advertisement_flag [1-bit] + reserved [1-bit]
uint8_t ble_medium_version = 0x02; // mediums::BleAdvertisement::Version::kV2
uint8_t socket_version =
0x02; // mediums::BleAdvertisement::SocketVersion::kV2
bool fast_advertisement = false; // Is Fast Advertisement
uint8_t ble_medium_advertisement_metadata_byte =
(ble_medium_version << 5) & kVersionBitmask;
ble_medium_advertisement_metadata_byte |=
(socket_version << 2) & kSocketVersionBitmask;
ble_medium_advertisement_metadata_byte |=
((fast_advertisement ? 1 : 0) << 1) & kFastAdvertisementFlagBitmask;
advertising_data_byte_array.at(0) =
static_cast<unsigned char>(ble_medium_advertisement_metadata_byte);
// (3 bytes) service_id_hash
for (int i = 0; i < 3; ++i) {
advertising_data_byte_array.at(1 + i) = static_cast<unsigned char>(0x00);
}
// (4 bytes) body_length
advertising_data_byte_array.at(7) = static_cast<unsigned char>(
0x9C); // max 156 bytes for Extended Advertising
// (1 byte) Nearby Connection version [3-bits] + pcp [5-bits]
uint8_t ble_connections_version =
0x01; // connections::BleAdvertisement::Version::kV1
uint8_t pcp = 0x02; // connections::Pcp::kP2pCluster
uint8_t ble_connections_advertisement_metadata_byte =
(ble_connections_version << 5) & kVersionBitmask;
ble_connections_advertisement_metadata_byte |= pcp & kPcpBitmask;
advertising_data_byte_array.at(8) =
static_cast<unsigned char>(ble_connections_advertisement_metadata_byte);
// (3 bytes) service_id_hash
for (int i = 0; i < 3; ++i) {
advertising_data_byte_array.at(9 + i) = static_cast<unsigned char>(0x00);
}
// (4 bytes) endpoint_id
for (int i = 0; i < 4; ++i) {
advertising_data_byte_array.at(12 + i) = static_cast<unsigned char>(0x00);
}
// (1 byte) endpoint_info_size
advertising_data_byte_array.at(16) = static_cast<unsigned char>(
0x83); // max 131-bytes for Extended Advertising
// =========endpoint_info [Max 131-bytes]============
// (1 byte) Nearby Share version [3-bits] + visibility [1-bit] + reserved
// [4-bits]
uint8_t nearby_share_version = 0x00; // nearby share v1
uint8_t visibility = 0x00; // [placeholder] sharing::Visibility::kAllContacts
uint8_t nearby_share_metadata_byte =
(nearby_share_version << 5) & kVersionBitmask;
nearby_share_metadata_byte |= ((visibility & kVisibilityBitmask) << 4);
advertising_data_byte_array.at(17) = static_cast<unsigned char>(0x00);
// (2 bytes) salt
for (int i = 0; i < 2; ++i) {
advertising_data_byte_array.at(18 + i) = static_cast<unsigned char>(0x00);
}
// (14 bytes) encrypted_metadata_key
for (int i = 0; i < 14; ++i) {
advertising_data_byte_array.at(20 + i) = static_cast<unsigned char>(0x00);
}
// [optional]
// (1 byte) human_readable_name_size
advertising_data_byte_array.at(34) = static_cast<unsigned char>(0x72);
// [optional]
// (max 114 bytes) human_readable_name
for (int i = 0; i < 114; ++i) {
advertising_data_byte_array.at(35 + i) = static_cast<unsigned char>(0x00);
}
// =========endpoint_info [131-bytes]============
// (6 bytes) bluetooth_mac_address
for (int i = 0; i < 6; ++i) {
advertising_data_byte_array.at(149 + i) = static_cast<unsigned char>(0x00);
}
// (1 byte) uwb_address_size
advertising_data_byte_array.at(155) = static_cast<unsigned char>(0x72);
// (8 bytes) uwb_address
for (int i = 0; i < 6; ++i) {
advertising_data_byte_array.at(156 + i) = static_cast<unsigned char>(0x00);
}
// (1 byte) extra_field [web_rtc_connectable]
advertising_data_byte_array.at(164) = static_cast<unsigned char>(0x72);
// (2 bytes) device_token
for (int i = 0; i < 2; ++i) {
advertising_data_byte_array.at(165 + i) = static_cast<unsigned char>(0x00);
}
ByteArray advertising_data(advertising_data_byte_array);
EXPECT_TRUE(ble_medium.StartAdvertising("NearbyShare", advertising_data, ""));
}
TEST(BleMedium, DISABLED_StopAdvertising) {
BluetoothAdapter bluetoothAdapter;
BleMedium ble_medium(bluetoothAdapter);
std::array<char, 2> advertising_data_byte_array;
// (2 bytes) 16-bit Service UUID 0xf3fe
advertising_data_byte_array.at(0) = static_cast<unsigned char>(0xf3);
advertising_data_byte_array.at(1) = static_cast<unsigned char>(0xfe);
ByteArray advertising_data(advertising_data_byte_array);
EXPECT_TRUE(
ble_medium.StartAdvertising("NearbyShare", advertising_data, "\xfe\xf3"));
EXPECT_TRUE(ble_medium.StopAdvertising("NearbyShare"));
}
TEST(BleMedium, DISABLED_StartScanning) {
BluetoothAdapter bluetoothAdapter;
BleMedium ble_medium(bluetoothAdapter);
EXPECT_TRUE(ble_medium.StartScanning(
"NearbyShare", "\xfe\xf3",
{.peripheral_discovered_cb = [](api::BlePeripheral& peripheral,
const std::string& service_id,
bool fast_advertisement) {},
.peripheral_lost_cb = [](api::BlePeripheral& peripheral,
const std::string& service_id) {}}));
}
TEST(BleMedium, DISABLED_ReceiveAdvertisement) {
absl::Notification advertisement_received_notification;
BluetoothAdapter bluetoothAdapter;
BleMedium ble_medium(bluetoothAdapter);
EXPECT_TRUE(ble_medium.StartScanning(
"NearbyShare", "\xfe\xf3",
{.peripheral_discovered_cb =
[&](api::BlePeripheral& peripheral, const std::string& service_id,
bool fast_advertisement) {
advertisement_received_notification.Notify();
},
.peripheral_lost_cb = [](api::BlePeripheral& peripheral,
const std::string& service_id) {}}));
EXPECT_TRUE(
advertisement_received_notification.WaitForNotificationWithTimeout(
absl::Seconds(5)));
}
TEST(BleMedium, DISABLED_StopScanning) {
BluetoothAdapter bluetoothAdapter;
BleMedium ble_medium(bluetoothAdapter);
EXPECT_TRUE(ble_medium.StartScanning(
"NearbyShare", "\xfe\xf3",
{.peripheral_discovered_cb =
[](api::BlePeripheral& peripheral, const std::string& service_id,
bool fast_advertisement) { EXPECT_TRUE(fast_advertisement); },
.peripheral_lost_cb = [](api::BlePeripheral& peripheral,
const std::string& service_id) {}}));
EXPECT_TRUE(ble_medium.StopScanning("NearbyShare"));
}
} // namespace
} // namespace windows
} // namespace nearby
@@ -1,60 +0,0 @@
// Copyright 2022 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 THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_PERIPHERAL_H_
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_PERIPHERAL_H_
#include <string>
#include "internal/platform/implementation/ble.h"
namespace nearby {
namespace windows {
// TODO(b/269152309): Implement BLE Peripheral
// This is just a fake stub to appease the BLE Medium abstraction. Windows
// does not support BLE GATT-based advertising/discovery and socket currently,
// so a BlePeripheral is not required. The remote device is recognized as a
// BluetoothClassicDevice instead.
// Opaque wrapper over a BLE peripheral. Must contain enough data about a
// particular BLE device to connect to its GATT server.
class BlePeripheral : public api::BlePeripheral {
public:
~BlePeripheral() override = default;
std::string GetName() const override { return name_; }
ByteArray GetAdvertisementBytes(
const std::string& service_id) const override {
return advertisement_data_;
}
void SetName(const std::string& name) {
name_ = name;
}
void SetAdvertisementBytes(ByteArray advertisement_bytes) {
advertisement_data_ = advertisement_bytes;
}
private:
std::string name_;
ByteArray advertisement_data_;
};
} // namespace windows
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_PERIPHERAL_H_
@@ -1,50 +0,0 @@
// Copyright 2022 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.
#include "internal/platform/implementation/windows/ble_socket.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/windows/ble_peripheral.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
namespace nearby {
namespace windows {
InputStream& BleSocket::GetInputStream() {
return fake_input_stream_;
}
OutputStream& BleSocket::GetOutputStream() {
return fake_output_stream_;
}
bool BleSocket::IsClosed() const {
absl::MutexLock lock(&mutex_);
return closed_;
}
Exception BleSocket::Close() {
absl::MutexLock lock(&mutex_);
return {Exception::kSuccess};
}
BlePeripheral* BleSocket::GetRemotePeripheral() {
absl::MutexLock lock(&mutex_);
return peripheral_;
}
} // namespace windows
} // namespace nearby
@@ -1,81 +0,0 @@
// Copyright 2022 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 THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_SOCKET_H_
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_SOCKET_H_
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/windows/ble.h"
#include "internal/platform/exception.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
namespace nearby {
namespace windows {
// TODO(b/269152309): Implement BLE Weave Socket
// This is just a fake stub to appease the BLE Medium abstraction. Windows
// does not support BLE Weave sockets currently. BLE is only used in the
// pre-connection phase handshake (advertising & discovering), connection is
// delegated to Bluetooth Classic Medium to establish RFCOMM socket.
class BleSocket : public api::BleSocket {
public:
~BleSocket() override;
// Returns the InputStream of this connected BleSocket.
InputStream& GetInputStream() override ABSL_LOCKS_EXCLUDED(mutex_);
// Returns the OutputStream of this connected BleSocket.
// This stream is for local side to write.
OutputStream& GetOutputStream() override ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true if socket is closed.
bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_);
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_);
// Returns valid BlePeripheral pointer if there is a connection, and
// nullptr otherwise.
BlePeripheral* GetRemotePeripheral() override ABSL_LOCKS_EXCLUDED(mutex_);
// Unhooked InputStream & OutputStream for empty implementation.
private:
class FakeInputStream : public InputStream {
~FakeInputStream() override = default;
ExceptionOr<ByteArray> Read(std::int64_t size) override {
return ExceptionOr<ByteArray>(Exception::kFailed);
}
Exception Close() override { return {.value = Exception::kFailed}; }
};
class FakeOutputStream : public OutputStream {
~FakeOutputStream() override = default;
Exception Write(const ByteArray& data) override {
return {.value = Exception::kFailed};
}
Exception Flush() override { return {.value = Exception::kFailed}; }
Exception Close() override { return {.value = Exception::kFailed}; }
};
FakeInputStream fake_input_stream_;
FakeOutputStream fake_output_stream_;
mutable absl::Mutex mutex_;
BlePeripheral* peripheral_;
bool closed_ ABSL_GUARDED_BY(mutex_) = false;
};
} // namespace windows
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_SOCKET_H_
@@ -41,7 +41,6 @@
#include "internal/platform/implementation/atomic_boolean.h"
#include "internal/platform/implementation/atomic_reference.h"
#include "internal/platform/implementation/awdl.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/bluetooth_classic.h"
@@ -60,7 +59,6 @@
#include "internal/platform/implementation/wifi_lan.h"
#include "internal/platform/implementation/windows/atomic_boolean.h"
#include "internal/platform/implementation/windows/atomic_reference.h"
#include "internal/platform/implementation/windows/ble_medium.h"
#include "internal/platform/implementation/windows/ble_v2.h"
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
#include "internal/platform/implementation/windows/bluetooth_classic_medium.h"
@@ -257,11 +255,6 @@ ImplementationPlatform::CreateBluetoothClassicMedium(
return std::make_unique<windows::BluetoothClassicMedium>(adapter);
}
std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(
BluetoothAdapter& adapter) {
return std::make_unique<windows::BleMedium>(adapter);
}
// TODO(b/184975123): replace with real implementation.
std::unique_ptr<api::ble_v2::BleMedium>
ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter& adapter) {