mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-15 07:06:11 -04:00
Add BLE V2 windows platform implementation (Phase 1)
This CL implements the scanning and advertising of Nearby BLE Medium Fast Advertisement with hardcoded advertisement data PiperOrigin-RevId: 446806137
This commit is contained in:
committed by
Copybara-Service
parent
8f4edf3c89
commit
6b88d326df
@@ -110,8 +110,8 @@ class ImplementationPlatform {
|
||||
static std::unique_ptr<BluetoothClassicMedium> CreateBluetoothClassicMedium(
|
||||
BluetoothAdapter&);
|
||||
static std::unique_ptr<BleMedium> CreateBleMedium(BluetoothAdapter&);
|
||||
static std::unique_ptr<ble_v2::BleMedium> CreateBleV2Medium(
|
||||
BluetoothAdapter&);
|
||||
static std::unique_ptr<api::ble_v2::BleMedium> CreateBleV2Medium(
|
||||
api::BluetoothAdapter&);
|
||||
static std::unique_ptr<ServerSyncMedium> CreateServerSyncMedium();
|
||||
static std::unique_ptr<WifiMedium> CreateWifiMedium();
|
||||
static std::unique_ptr<WifiLanMedium> CreateWifiLanMedium();
|
||||
|
||||
@@ -48,6 +48,7 @@ cc_library(
|
||||
name = "comm",
|
||||
hdrs = [
|
||||
"ble.h",
|
||||
"ble_v2.h",
|
||||
"bluetooth_adapter.h",
|
||||
"bluetooth_classic.h",
|
||||
"bluetooth_classic_device.h",
|
||||
@@ -100,6 +101,7 @@ cc_library(
|
||||
cc_library(
|
||||
name = "windows",
|
||||
srcs = [
|
||||
"ble_v2.cc",
|
||||
"bluetooth_adapter.cc",
|
||||
"bluetooth_classic_device.cc",
|
||||
"bluetooth_classic_medium.cc",
|
||||
@@ -165,6 +167,7 @@ cc_test(
|
||||
srcs = [
|
||||
"atomic_boolean_test.cc",
|
||||
"atomic_reference_test.cc",
|
||||
"ble_v2_test.cc",
|
||||
"count_down_latch_test.cc",
|
||||
"crypto_test.cc",
|
||||
"executor_test.cc",
|
||||
|
||||
@@ -0,0 +1,453 @@
|
||||
// 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_v2.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/shared/count_down_latch.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"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::location::nearby::api::ble_v2::BleAdvertisementData;
|
||||
using ::location::nearby::api::ble_v2::BleSocket;
|
||||
using ::location::nearby::api::ble_v2::BleSocketLifeCycleCallback;
|
||||
using ::location::nearby::api::ble_v2::ClientGattConnection;
|
||||
using ::location::nearby::api::ble_v2::PowerMode;
|
||||
using ::location::nearby::api::ble_v2::ServerGattConnectionCallback;
|
||||
using ::winrt::Windows::Devices::Bluetooth::BluetoothError;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisement;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementDataSection;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementDataTypes;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisher;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisherStatus;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisherStatusChangedEventArgs;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementReceivedEventArgs;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcherStatus;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEScanningMode;
|
||||
using ::winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
template <typename T>
|
||||
using IVector = winrt::Windows::Foundation::Collections::IVector<T>;
|
||||
|
||||
std::string PowerModeToName(PowerMode power_mode) {
|
||||
switch (power_mode) {
|
||||
case PowerMode::kUltraLow:
|
||||
return "UltraLow";
|
||||
case PowerMode::kLow:
|
||||
return "Low";
|
||||
case PowerMode::kMedium:
|
||||
return "Medium";
|
||||
case PowerMode::kHigh:
|
||||
return "High";
|
||||
case PowerMode::kUnknown:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string BleV2Peripheral::GetId() const { return ""; }
|
||||
|
||||
BleV2Medium::BleV2Medium(api::BluetoothAdapter& adapter)
|
||||
: adapter_(dynamic_cast<BluetoothAdapter*>(&adapter)) {}
|
||||
|
||||
BleV2Medium::~BleV2Medium() {}
|
||||
|
||||
// TODO(edwinwu): Modify advertising abstraction APIs and fit all data into one
|
||||
// advertisement packet and populate accordingly
|
||||
bool BleV2Medium::StartAdvertising(
|
||||
const BleAdvertisementData& advertising_data,
|
||||
const BleAdvertisementData& scan_response_data, PowerMode power_mode) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Windows Ble StartAdvertising:, advertising_data.service_uuids size="
|
||||
<< advertising_data.service_uuids.size()
|
||||
<< ", scan_response_data.service_data size="
|
||||
<< scan_response_data.service_data.size()
|
||||
<< ", power_mode=" << PowerModeToName(power_mode);
|
||||
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
// (AD type 0x16) Service Data
|
||||
constexpr uint8_t kCopresenceServiceUuid[] = {0xf3, 0xfe};
|
||||
DataWriter data_writer;
|
||||
|
||||
// (2 bytes) 16-bit Service UUID 0xf3fe
|
||||
data_writer.WriteByte(kCopresenceServiceUuid[1]); // 0xfe
|
||||
data_writer.WriteByte(kCopresenceServiceUuid[0]); // 0xf3
|
||||
|
||||
// (1 byte) version [3-bits] + socket_version [3-bits] +
|
||||
// fast_advertisement_flag [1-bit] + reserved [1-bit]
|
||||
data_writer.WriteByte(0x00);
|
||||
|
||||
// (1 byte) body_length
|
||||
data_writer.WriteByte(0x00);
|
||||
|
||||
// (1 byte) Nearby Connection version [3-bits] + pcp [5-bits]
|
||||
data_writer.WriteByte(0x00);
|
||||
|
||||
// (4 bytes) endpoint_id
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
data_writer.WriteByte(0x00);
|
||||
}
|
||||
|
||||
// (1 byte) endpoint_info_size
|
||||
data_writer.WriteByte(0x11); // always 17-bytes for Fast Advertisement
|
||||
|
||||
// =========endpoint_info [17-bytes]============
|
||||
// (1 byte) Nearby Share version [3-bits] + visibility [1-bit] + reserved
|
||||
// [4-bits]
|
||||
data_writer.WriteByte(0x00);
|
||||
|
||||
// (2 bytes) salt
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
data_writer.WriteByte(0x00);
|
||||
}
|
||||
|
||||
// (14 bytes) encrypted_metadata_key
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
data_writer.WriteByte(0x00);
|
||||
}
|
||||
// =========endpoint_info [17-bytes]============
|
||||
|
||||
// (2 bytes) device_token
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
data_writer.WriteByte(0x00);
|
||||
}
|
||||
|
||||
BluetoothLEAdvertisementDataSection service_data =
|
||||
BluetoothLEAdvertisementDataSection(0x16, data_writer.DetachBuffer());
|
||||
|
||||
IVector<BluetoothLEAdvertisementDataSection> data_sections =
|
||||
advertisement_.DataSections();
|
||||
data_sections.Append(service_data);
|
||||
advertisement_.DataSections() = data_sections;
|
||||
|
||||
publisher_ = BluetoothLEAdvertisementPublisher(advertisement_);
|
||||
|
||||
publisher_started_callback_ = [this]() {
|
||||
advertising_started_ = true;
|
||||
advertising_stopped_ = false;
|
||||
};
|
||||
publisher_error_callback_ = [this]() {
|
||||
advertising_error_ = true;
|
||||
advertising_started_ = false;
|
||||
advertising_stopped_ = false;
|
||||
};
|
||||
|
||||
publisher_token_ =
|
||||
publisher_.StatusChanged({this, &BleV2Medium::PublisherHandler});
|
||||
|
||||
publisher_.Start();
|
||||
|
||||
while (!advertising_started_) {
|
||||
if (advertising_error_) {
|
||||
return false;
|
||||
}
|
||||
if (publisher_.Status() ==
|
||||
BluetoothLEAdvertisementPublisherStatus::Started) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2Medium::StopAdvertising() {
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StopAdvertising";
|
||||
absl::MutexLock lock(&mutex_);
|
||||
publisher_stopped_callback_ = [this]() {
|
||||
advertising_stopped_ = true;
|
||||
advertising_started_ = false;
|
||||
};
|
||||
publisher_error_callback_ = [this]() {
|
||||
advertising_error_ = true;
|
||||
advertising_stopped_ = false;
|
||||
advertising_started_ = false;
|
||||
};
|
||||
|
||||
publisher_.Stop();
|
||||
|
||||
while (!advertising_stopped_) {
|
||||
if (advertising_error_) {
|
||||
return false;
|
||||
}
|
||||
if (publisher_.Status() ==
|
||||
BluetoothLEAdvertisementPublisherStatus::Stopped) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2Medium::StartScanning(const std::vector<std::string>& service_uuids,
|
||||
PowerMode power_mode, ScanCallback callback) {
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartScanning";
|
||||
absl::MutexLock lock(&mutex_);
|
||||
watcher_started_callback_ = [this]() {
|
||||
scanning_started_ = true;
|
||||
scanning_stopped_ = false;
|
||||
};
|
||||
watcher_error_callback_ = [this]() {
|
||||
scanning_error_ = true;
|
||||
scanning_started_ = false;
|
||||
scanning_stopped_ = false;
|
||||
};
|
||||
|
||||
watcher_token_ = watcher_.Stopped({this, &BleV2Medium::WatcherHandler});
|
||||
advertisement_received_token_ =
|
||||
watcher_.Received({this, &BleV2Medium::AdvertisementReceivedHandler});
|
||||
|
||||
// Active mode indicates that scan request packes will be sent to query for
|
||||
// Scan Response
|
||||
watcher_.ScanningMode(BluetoothLEScanningMode::Active);
|
||||
watcher_.Start();
|
||||
|
||||
while (!scanning_started_) {
|
||||
if (scanning_error_) {
|
||||
return false;
|
||||
}
|
||||
if (watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Created) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2Medium::StopScanning() {
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StopScanning";
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
watcher_stopped_callback_ = [this]() {
|
||||
scanning_stopped_ = true;
|
||||
scanning_started_ = false;
|
||||
};
|
||||
watcher_error_callback_ = [this]() {
|
||||
scanning_error_ = true;
|
||||
scanning_stopped_ = false;
|
||||
scanning_started_ = false;
|
||||
};
|
||||
|
||||
watcher_.Stop();
|
||||
|
||||
while (!scanning_stopped_) {
|
||||
if (scanning_error_) {
|
||||
return false;
|
||||
}
|
||||
if (watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Stopped) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::GattServer> BleV2Medium::StartGattServer(
|
||||
ServerGattConnectionCallback callback) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool BleV2Medium::StartListeningForIncomingBleSockets(
|
||||
const api::ble_v2::ServerBleSocketLifeCycleCallback& callback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void BleV2Medium::StopListeningForIncomingBleSockets() {}
|
||||
|
||||
std::unique_ptr<ClientGattConnection> BleV2Medium::ConnectToGattServer(
|
||||
api::ble_v2::BlePeripheral& peripheral, Mtu mtu, PowerMode power_mode,
|
||||
api::ble_v2::ClientGattConnectionCallback callback) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<BleSocket> BleV2Medium::EstablishBleSocket(
|
||||
api::ble_v2::BlePeripheral* peripheral,
|
||||
const BleSocketLifeCycleCallback& callback) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void BleV2Medium::PublisherHandler(
|
||||
BluetoothLEAdvertisementPublisher publisher,
|
||||
BluetoothLEAdvertisementPublisherStatusChangedEventArgs args) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
switch (args.Status()) {
|
||||
case BluetoothLEAdvertisementPublisherStatus::Started:
|
||||
publisher_started_callback_();
|
||||
break;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Stopped:
|
||||
publisher_stopped_callback_();
|
||||
publisher_.StatusChanged(publisher_token_);
|
||||
break;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Aborted:
|
||||
switch (args.Error()) {
|
||||
case BluetoothError::RadioNotAvailable:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"radio not available.";
|
||||
break;
|
||||
case BluetoothError::ResourceInUse:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium advertising failed due to resource in use.";
|
||||
break;
|
||||
case BluetoothError::DisabledByPolicy:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"disabled by policy.";
|
||||
break;
|
||||
case BluetoothError::DisabledByUser:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"disabled by user.";
|
||||
break;
|
||||
case BluetoothError::NotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"hardware not supported.";
|
||||
break;
|
||||
case BluetoothError::TransportNotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"transport not supported.";
|
||||
break;
|
||||
case BluetoothError::ConsentRequired:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"consent required.";
|
||||
break;
|
||||
case BluetoothError::OtherError:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium advertising failed due to unknown errors.";
|
||||
break;
|
||||
default:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium advertising failed due to unknown errors.";
|
||||
break;
|
||||
}
|
||||
publisher_error_callback_();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BleV2Medium::WatcherHandler(
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs args) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
switch (args.Error()) {
|
||||
case BluetoothError::RadioNotAvailable:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to radio not available.";
|
||||
break;
|
||||
case BluetoothError::ResourceInUse:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to resource in use.";
|
||||
break;
|
||||
case BluetoothError::DisabledByPolicy:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to disabled by policy.";
|
||||
break;
|
||||
case BluetoothError::DisabledByUser:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to disabled by user.";
|
||||
break;
|
||||
case BluetoothError::NotSupported:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to hardware not supported.";
|
||||
break;
|
||||
case BluetoothError::TransportNotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium scanning failed due to "
|
||||
"transport not supported.";
|
||||
break;
|
||||
case BluetoothError::ConsentRequired:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to consent required.";
|
||||
break;
|
||||
case BluetoothError::OtherError:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to unknown errors.";
|
||||
break;
|
||||
case BluetoothError::Success:
|
||||
if (watcher_stopped_callback_ != nullptr &&
|
||||
watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Started) {
|
||||
watcher_started_callback_();
|
||||
}
|
||||
if (watcher_stopped_callback_ != nullptr &&
|
||||
watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Stopped) {
|
||||
watcher_stopped_callback_();
|
||||
watcher_.Stopped(watcher_token_);
|
||||
watcher_.Received(advertisement_received_token_);
|
||||
}
|
||||
default:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to unknown errors.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BleV2Medium::AdvertisementReceivedHandler(
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
BluetoothLEAdvertisementReceivedEventArgs args) {
|
||||
// Handle all BLE advertisements and determine whether the BLE Medium
|
||||
// Advertisement Scan Response packet (containing Copresence UUID 0xFEF3) has
|
||||
// been received in the handler
|
||||
std::array<uint8_t, 8> bluetooth_base_array = {
|
||||
static_cast<uint8_t>(0x80), static_cast<uint8_t>(0x00),
|
||||
static_cast<uint8_t>(0x00), static_cast<uint8_t>(0x80),
|
||||
static_cast<uint8_t>(0x5F), static_cast<uint8_t>(0x9B),
|
||||
static_cast<uint8_t>(0x34), static_cast<uint8_t>(0xFB)};
|
||||
winrt::guid kCopresenceServiceUuid128bit(
|
||||
static_cast<uint32_t>(0x0000FEF3), static_cast<uint16_t>(0x0000),
|
||||
static_cast<uint16_t>(0x1000), bluetooth_base_array);
|
||||
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
if (args.IsScanResponse()) {
|
||||
IVector<winrt::guid> guids = args.Advertisement().ServiceUuids();
|
||||
bool scan_response_found = false;
|
||||
for (const winrt::guid& uuid : guids) {
|
||||
if (uuid == kCopresenceServiceUuid128bit) {
|
||||
scan_response_found = true;
|
||||
}
|
||||
}
|
||||
if (scan_response_found == true) {
|
||||
BleV2Peripheral peripheral;
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
scan_response_received_callback_.advertisement_found_cb(
|
||||
peripheral, advertisement_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,134 @@
|
||||
// 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_V2_H_
|
||||
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_V2_H_
|
||||
|
||||
#include <functional>
|
||||
#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_v2.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.Advertisement.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
class BleV2Peripheral : public api::ble_v2::BlePeripheral {
|
||||
public:
|
||||
std::string GetId() const override;
|
||||
};
|
||||
|
||||
// Container of operations that can be performed over the BLE medium.
|
||||
class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
public:
|
||||
explicit BleV2Medium(api::BluetoothAdapter& adapter);
|
||||
~BleV2Medium() override;
|
||||
|
||||
// Returns true once the Ble advertising has been initiated.
|
||||
bool StartAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData& advertising_data,
|
||||
const api::ble_v2::BleAdvertisementData& scan_response_data,
|
||||
api::ble_v2::PowerMode power_mode) override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopAdvertising() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool StartScanning(const std::vector<std::string>& service_uuids,
|
||||
api::ble_v2::PowerMode power_mode,
|
||||
ScanCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopScanning() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::GattServer> StartGattServer(
|
||||
api::ble_v2::ServerGattConnectionCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StartListeningForIncomingBleSockets(
|
||||
const api::ble_v2::ServerBleSocketLifeCycleCallback& callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void StopListeningForIncomingBleSockets() override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::ClientGattConnection> ConnectToGattServer(
|
||||
api::ble_v2::BlePeripheral& peripheral, Mtu mtu,
|
||||
api::ble_v2::PowerMode power_mode,
|
||||
api::ble_v2::ClientGattConnectionCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::BleSocket> EstablishBleSocket(
|
||||
api::ble_v2::BlePeripheral* peripheral,
|
||||
const api::ble_v2::BleSocketLifeCycleCallback& callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
BluetoothAdapter& GetAdapter() { return *adapter_; }
|
||||
|
||||
private:
|
||||
absl::Mutex mutex_;
|
||||
BluetoothAdapter* adapter_;
|
||||
ByteArray advertisement_byte_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
bool advertising_started_ = false;
|
||||
bool advertising_error_ = false;
|
||||
bool advertising_stopped_ = false;
|
||||
|
||||
bool scanning_started_ = false;
|
||||
bool scanning_error_ = false;
|
||||
bool scanning_stopped_ = false;
|
||||
|
||||
// WinRT objects
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisher publisher_;
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher_;
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisement
|
||||
advertisement_;
|
||||
|
||||
winrt::event_token publisher_token_;
|
||||
void PublisherHandler(
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisher publisher,
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisherStatusChangedEventArgs args);
|
||||
std::function<void()> publisher_started_callback_ ABSL_GUARDED_BY(mutex_);
|
||||
std::function<void()> publisher_stopped_callback_ ABSL_GUARDED_BY(mutex_);
|
||||
std::function<void()> publisher_error_callback_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
winrt::event_token watcher_token_;
|
||||
void WatcherHandler(winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs args);
|
||||
std::function<void()> watcher_started_callback_ ABSL_GUARDED_BY(mutex_);
|
||||
std::function<void()> watcher_stopped_callback_ ABSL_GUARDED_BY(mutex_);
|
||||
std::function<void()> watcher_error_callback_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
winrt::event_token advertisement_received_token_;
|
||||
void AdvertisementReceivedHandler(
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementReceivedEventArgs args);
|
||||
ScanCallback scan_response_received_callback_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLE_V2_H_
|
||||
@@ -0,0 +1,94 @@
|
||||
// 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_v2.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
|
||||
TEST(BleV2Medium, DISABLED_StartAdvertising) {
|
||||
BluetoothAdapter bluetoothAdapter;
|
||||
BleV2Medium blev2_medium(bluetoothAdapter);
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertising_data;
|
||||
api::ble_v2::BleAdvertisementData scan_response_data;
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StartAdvertising(
|
||||
advertising_data, scan_response_data, api::ble_v2::PowerMode::kHigh));
|
||||
}
|
||||
|
||||
TEST(BleV2Medium, DISABLED_StopAdvertising) {
|
||||
BluetoothAdapter bluetoothAdapter;
|
||||
BleV2Medium blev2_medium(bluetoothAdapter);
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertising_data;
|
||||
api::ble_v2::BleAdvertisementData scan_response_data;
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StartAdvertising(
|
||||
advertising_data, scan_response_data, api::ble_v2::PowerMode::kHigh));
|
||||
EXPECT_TRUE(blev2_medium.StopAdvertising());
|
||||
}
|
||||
|
||||
TEST(BleV2Medium, DISABLED_StartScanning) {
|
||||
bool scan_response_received = false;
|
||||
absl::Notification scan_response_notification;
|
||||
|
||||
BluetoothAdapter bluetoothAdapter;
|
||||
BleV2Medium blev2_medium(bluetoothAdapter);
|
||||
std::vector<std::string> service_uuids;
|
||||
|
||||
api::ble_v2::BleMedium::ScanCallback callback;
|
||||
callback.advertisement_found_cb =
|
||||
[&scan_response_received, &scan_response_notification](
|
||||
api::ble_v2::BlePeripheral& peripheral,
|
||||
const api::ble_v2::BleAdvertisementData& advertisement_data) {
|
||||
scan_response_received = true;
|
||||
scan_response_notification.Notify();
|
||||
};
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StartScanning(
|
||||
service_uuids, api::ble_v2::PowerMode::kHigh, callback));
|
||||
|
||||
EXPECT_TRUE(scan_response_notification.WaitForNotificationWithTimeout(
|
||||
absl::Seconds(5)));
|
||||
EXPECT_TRUE(scan_response_received);
|
||||
}
|
||||
|
||||
TEST(BleV2Medium, DISABLED_StopScanning) {
|
||||
BluetoothAdapter bluetoothAdapter;
|
||||
BleV2Medium blev2_medium(bluetoothAdapter);
|
||||
std::vector<std::string> service_uuids;
|
||||
|
||||
api::ble_v2::BleMedium::ScanCallback callback;
|
||||
callback.advertisement_found_cb =
|
||||
[](api::ble_v2::BlePeripheral& peripheral,
|
||||
const api::ble_v2::BleAdvertisementData& advertisement_data) {};
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StartScanning(
|
||||
service_uuids, api::ble_v2::PowerMode::kHigh, callback));
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StopScanning());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -18,15 +18,16 @@
|
||||
#include <shlobj.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <xstring>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "internal/platform/implementation/shared/count_down_latch.h"
|
||||
#include "internal/platform/implementation/shared/file.h"
|
||||
#include "internal/platform/implementation/windows/atomic_boolean.h"
|
||||
#include "internal/platform/implementation/windows/atomic_reference.h"
|
||||
#include "internal/platform/implementation/windows/ble.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"
|
||||
#include "internal/platform/implementation/windows/cancelable.h"
|
||||
@@ -42,8 +43,8 @@
|
||||
#include "internal/platform/implementation/windows/submittable_executor.h"
|
||||
#include "internal/platform/implementation/windows/webrtc.h"
|
||||
#include "internal/platform/implementation/windows/wifi.h"
|
||||
#include "internal/platform/implementation/windows/wifi_lan.h"
|
||||
#include "internal/platform/implementation/windows/wifi_hotspot.h"
|
||||
#include "internal/platform/implementation/windows/wifi_lan.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
@@ -214,9 +215,9 @@ std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(
|
||||
}
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::unique_ptr<ble_v2::BleMedium> ImplementationPlatform::CreateBleV2Medium(
|
||||
BluetoothAdapter&) {
|
||||
return nullptr;
|
||||
std::unique_ptr<api::ble_v2::BleMedium>
|
||||
ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter& adapter) {
|
||||
return std::make_unique<windows::BleV2Medium>(adapter);
|
||||
}
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
|
||||
Reference in New Issue
Block a user