diff --git a/internal/platform/implementation/platform.h b/internal/platform/implementation/platform.h index d447267d..5d013310 100644 --- a/internal/platform/implementation/platform.h +++ b/internal/platform/implementation/platform.h @@ -110,8 +110,8 @@ class ImplementationPlatform { static std::unique_ptr CreateBluetoothClassicMedium( BluetoothAdapter&); static std::unique_ptr CreateBleMedium(BluetoothAdapter&); - static std::unique_ptr CreateBleV2Medium( - BluetoothAdapter&); + static std::unique_ptr CreateBleV2Medium( + api::BluetoothAdapter&); static std::unique_ptr CreateServerSyncMedium(); static std::unique_ptr CreateWifiMedium(); static std::unique_ptr CreateWifiLanMedium(); diff --git a/internal/platform/implementation/windows/BUILD b/internal/platform/implementation/windows/BUILD index 5611fe1b..8f6969b0 100644 --- a/internal/platform/implementation/windows/BUILD +++ b/internal/platform/implementation/windows/BUILD @@ -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", diff --git a/internal/platform/implementation/windows/ble_v2.cc b/internal/platform/implementation/windows/ble_v2.cc new file mode 100644 index 00000000..1658227a --- /dev/null +++ b/internal/platform/implementation/windows/ble_v2.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 +#include +#include + +#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 +using IVector = winrt::Windows::Foundation::Collections::IVector; + +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(&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 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& 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 BleV2Medium::StartGattServer( + ServerGattConnectionCallback callback) { + return nullptr; +} + +bool BleV2Medium::StartListeningForIncomingBleSockets( + const api::ble_v2::ServerBleSocketLifeCycleCallback& callback) { + return false; +} + +void BleV2Medium::StopListeningForIncomingBleSockets() {} + +std::unique_ptr BleV2Medium::ConnectToGattServer( + api::ble_v2::BlePeripheral& peripheral, Mtu mtu, PowerMode power_mode, + api::ble_v2::ClientGattConnectionCallback callback) { + return nullptr; +} + +std::unique_ptr 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 bluetooth_base_array = { + static_cast(0x80), static_cast(0x00), + static_cast(0x00), static_cast(0x80), + static_cast(0x5F), static_cast(0x9B), + static_cast(0x34), static_cast(0xFB)}; + winrt::guid kCopresenceServiceUuid128bit( + static_cast(0x0000FEF3), static_cast(0x0000), + static_cast(0x1000), bluetooth_base_array); + + absl::MutexLock lock(&mutex_); + + if (args.IsScanResponse()) { + IVector 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 diff --git a/internal/platform/implementation/windows/ble_v2.h b/internal/platform/implementation/windows/ble_v2.h new file mode 100644 index 00000000..0c50ac84 --- /dev/null +++ b/internal/platform/implementation/windows/ble_v2.h @@ -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 +#include +#include + +#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& 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 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 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 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 publisher_started_callback_ ABSL_GUARDED_BY(mutex_); + std::function publisher_stopped_callback_ ABSL_GUARDED_BY(mutex_); + std::function 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 watcher_started_callback_ ABSL_GUARDED_BY(mutex_); + std::function watcher_stopped_callback_ ABSL_GUARDED_BY(mutex_); + std::function 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_ diff --git a/internal/platform/implementation/windows/ble_v2_test.cc b/internal/platform/implementation/windows/ble_v2_test.cc new file mode 100644 index 00000000..d4038310 --- /dev/null +++ b/internal/platform/implementation/windows/ble_v2_test.cc @@ -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 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 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 diff --git a/internal/platform/implementation/windows/platform.cc b/internal/platform/implementation/windows/platform.cc index 82b933b1..0ad554fc 100644 --- a/internal/platform/implementation/windows/platform.cc +++ b/internal/platform/implementation/windows/platform.cc @@ -18,15 +18,16 @@ #include #include -#include -#include +#include #include +#include #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 ImplementationPlatform::CreateBleMedium( } // TODO(b/184975123): replace with real implementation. -std::unique_ptr ImplementationPlatform::CreateBleV2Medium( - BluetoothAdapter&) { - return nullptr; +std::unique_ptr +ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter& adapter) { + return std::make_unique(adapter); } // TODO(b/184975123): replace with real implementation.