mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Remove BLE V1 codes
PiperOrigin-RevId: 811369802
This commit is contained in:
committed by
Copybara-Service
parent
72088b7fe2
commit
5fbef9e11e
@@ -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>();
|
||||
|
||||
@@ -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_
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
@@ -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>(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user