diff --git a/presence/BUILD b/presence/BUILD index ee4d0e94..42b3827a 100644 --- a/presence/BUILD +++ b/presence/BUILD @@ -63,6 +63,7 @@ cc_library( "//internal/platform:base", "//internal/platform:logging", "//internal/proto:credential_cc_proto", + "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@com_google_absl//absl/types:variant", diff --git a/presence/implementation/BUILD b/presence/implementation/BUILD index 57a37c34..f3038e6a 100644 --- a/presence/implementation/BUILD +++ b/presence/implementation/BUILD @@ -128,6 +128,7 @@ cc_test( ":internal", "//internal/platform/implementation/g3", # build_cleaner: keep "//presence:types", + "//presence/implementation/mediums", "@com_github_protobuf_matchers//protobuf-matchers", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", diff --git a/presence/implementation/advertisement_factory.cc b/presence/implementation/advertisement_factory.cc index 4613901a..1af9ae56 100644 --- a/presence/implementation/advertisement_factory.cc +++ b/presence/implementation/advertisement_factory.cc @@ -24,7 +24,7 @@ #include "internal/proto/credential.pb.h" #include "presence/data_element.h" #include "presence/implementation/base_broadcast_request.h" -#include "presence/implementation/mediums/ble.h" +#include "presence/implementation/mediums/advertisement_data.h" namespace nearby { namespace presence { @@ -93,9 +93,9 @@ std::string SerializeAction(const Action& action) { } // namespace -absl::StatusOr AdvertisementFactory::CreateAdvertisement( +absl::StatusOr AdvertisementFactory::CreateAdvertisement( const BaseBroadcastRequest& request) const { - BleAdvertisementData advert = {}; + AdvertisementData advert = {}; if (absl::holds_alternative( request.variant)) { return CreateBaseNpAdvertisement(request); @@ -103,12 +103,11 @@ absl::StatusOr AdvertisementFactory::CreateAdvertisement( return advert; } -absl::StatusOr +absl::StatusOr AdvertisementFactory::CreateBaseNpAdvertisement( const BaseBroadcastRequest& request) const { const auto& presence = absl::get(request.variant); - BleAdvertisementData advert{}; std::string payload; payload.reserve(kMaxBaseNpAdvSize); payload.push_back(kBaseVersion); @@ -173,9 +172,8 @@ AdvertisementFactory::CreateBaseNpAdvertisement( return result; } } - advert.service_data.insert( - {kPresenceServiceUuid, location::nearby::ByteArray(payload)}); - return advert; + return AdvertisementData{.is_extended_advertisement = false, + .content = payload}; } } // namespace presence diff --git a/presence/implementation/advertisement_factory.h b/presence/implementation/advertisement_factory.h index 69025277..984ab753 100644 --- a/presence/implementation/advertisement_factory.h +++ b/presence/implementation/advertisement_factory.h @@ -19,28 +19,25 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" -#include "internal/platform/implementation/ble_v2.h" #include "presence/implementation/base_broadcast_request.h" #include "presence/implementation/credential_manager.h" +#include "presence/implementation/mediums/advertisement_data.h" namespace nearby { namespace presence { -// An opaque container with the advertisement data. -using ::location::nearby::api::ble_v2::BleAdvertisementData; - -/** Builds BLE advertisements from broadcast requests. */ +// Builds BLE advertisements from broadcast requests. class AdvertisementFactory { public: explicit AdvertisementFactory(CredentialManager* credential_manager) : credential_manager_(*credential_manager) {} - /** Returns a BLE advertisement for given `request` */ - absl::StatusOr CreateAdvertisement( + // Returns a BLE advertisement for given `request. + absl::StatusOr CreateAdvertisement( const BaseBroadcastRequest& request) const; private: - absl::StatusOr CreateBaseNpAdvertisement( + absl::StatusOr CreateBaseNpAdvertisement( const BaseBroadcastRequest& request) const; CredentialManager& credential_manager_; diff --git a/presence/implementation/advertisement_factory_test.cc b/presence/implementation/advertisement_factory_test.cc index 495baf62..26644762 100644 --- a/presence/implementation/advertisement_factory_test.cc +++ b/presence/implementation/advertisement_factory_test.cc @@ -25,6 +25,7 @@ #include "presence/data_element.h" #include "presence/implementation/action_factory.h" #include "presence/implementation/credential_manager_impl.h" +#include "presence/implementation/mediums/advertisement_data.h" namespace nearby { namespace presence { @@ -66,17 +67,13 @@ TEST(AdvertisementFactory, CreateAdvertisementFromPrivateIdentity) { .WillOnce(Return(metadata_key + absl::HexStringToBytes("50515253"))); AdvertisementFactory factory(&credential_manager); - absl::StatusOr result = + absl::StatusOr result = factory.CreateAdvertisement(request); ASSERT_OK(result); - auto service_data = result->service_data; - ASSERT_EQ(service_data.size(), 1); - for (auto i : service_data) { - EXPECT_EQ(i.first.Get16BitAsString(), "FCF1"); - auto advertisement = absl::BytesToHexString(i.second.AsStringView()); - EXPECT_EQ(advertisement, "00414142101112131415161718192021222350515253"); - } + EXPECT_FALSE(result->is_extended_advertisement); + EXPECT_EQ(absl::BytesToHexString(result->content), + "00414142101112131415161718192021222350515253"); } TEST(AdvertisementFactory, CreateAdvertisementFromPublicIdentity) { @@ -93,17 +90,12 @@ TEST(AdvertisementFactory, CreateAdvertisementFromPublicIdentity) { .SetAction(action)); AdvertisementFactory factory(&credential_manager); - absl::StatusOr result = + absl::StatusOr result = factory.CreateAdvertisement(request); ASSERT_OK(result); - auto service_data = result->service_data; - EXPECT_EQ(service_data.size(), 1); - for (auto i : service_data) { - EXPECT_EQ(i.first.Get16BitAsString(), "FCF1"); - auto advertisement = absl::BytesToHexString(i.second.AsStringView()); - EXPECT_EQ(advertisement, "000320414236050080"); - } + EXPECT_FALSE(result->is_extended_advertisement); + EXPECT_EQ(absl::BytesToHexString(result->content), "000320414236050080"); } TEST(AdvertisementFactory, CreateAdvertisementFailsWhenEncryptionFails) { diff --git a/presence/implementation/mediums/BUILD b/presence/implementation/mediums/BUILD index 792d2658..dd2ea5c3 100644 --- a/presence/implementation/mediums/BUILD +++ b/presence/implementation/mediums/BUILD @@ -18,6 +18,7 @@ cc_library( srcs = [ ], hdrs = [ + "advertisement_data.h", "ble.h", "mediums.h", ], diff --git a/presence/implementation/mediums/advertisement_data.h b/presence/implementation/mediums/advertisement_data.h new file mode 100644 index 00000000..654f89b9 --- /dev/null +++ b/presence/implementation/mediums/advertisement_data.h @@ -0,0 +1,34 @@ +// 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_PRESENCE_IMPLEMENTATION_MEDIUMS_ADVERTISEMENT_DATA_H_ +#define THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_MEDIUMS_ADVERTISEMENT_DATA_H_ + +#include + +namespace nearby { +namespace presence { + +// Nearby Presence advertisement data over the air. +struct AdvertisementData { + // If true, the advertisement needs to be broadcasted over BLE 5.0. + bool is_extended_advertisement; + // The advertised data. + std::string content; +}; + +} // namespace presence +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_MEDIUMS_ADVERTISEMENT_DATA_H_ diff --git a/presence/implementation/mediums/ble.h b/presence/implementation/mediums/ble.h index ee778303..24b753b8 100644 --- a/presence/implementation/mediums/ble.h +++ b/presence/implementation/mediums/ble.h @@ -21,6 +21,7 @@ #include "internal/platform/ble_v2.h" #include "internal/platform/bluetooth_adapter.h" #include "internal/platform/uuid.h" +#include "presence/implementation/mediums/advertisement_data.h" #include "presence/power_mode.h" #include "presence/scan_request.h" @@ -62,13 +63,12 @@ class Ble { // Starts broadcasting NP advertisement in `payload`. The caller should use // the returned `AdvertisingSession` to stop the broadcast. std::unique_ptr StartAdvertising( - absl::string_view payload, bool is_extended_advertisement, - PowerMode power_mode, AdvertisingCallback callback) { - BleAdvertisementData advertising_data = {.is_extended_advertisement = - is_extended_advertisement}; + const AdvertisementData& payload, PowerMode power_mode, + AdvertisingCallback callback) { + BleAdvertisementData advertising_data = { + .is_extended_advertisement = payload.is_extended_advertisement}; advertising_data.service_data.insert( - {kPresenceServiceUuid, - location::nearby::ByteArray(std::string(payload))}); + {kPresenceServiceUuid, location::nearby::ByteArray(payload.content)}); AdvertiseParameters advertise_set_parameters = { .tx_power_level = ConvertPowerModeToPowerLevel(power_mode), .is_connectable = true, diff --git a/presence/implementation/mediums/ble_test.cc b/presence/implementation/mediums/ble_test.cc index 8613c139..208cae56 100644 --- a/presence/implementation/mediums/ble_test.cc +++ b/presence/implementation/mediums/ble_test.cc @@ -28,6 +28,7 @@ #include "internal/platform/medium_environment.h" #include "internal/platform/uuid.h" #include "presence/data_element.h" +#include "presence/implementation/mediums/advertisement_data.h" #include "presence/scan_request.h" namespace nearby { @@ -139,7 +140,8 @@ TEST_P(BleTest, AdvertiseAndScan) { Ble client(client_adapter); location::nearby::BluetoothAdapter server_adapter; Ble server(server_adapter); - std::string advert_data = "my advertisement"; + AdvertisementData advert_data = {.is_extended_advertisement = false, + .content = "my advertisement"}; ScanRequest scan_request{ .power_mode = PowerMode::kBalanced, }; @@ -156,8 +158,7 @@ TEST_P(BleTest, AdvertiseAndScan) { }}); std::unique_ptr advertising_session = server.StartAdvertising( - advert_data, /*is_extended_advertisement=*/false, - PowerMode::kBalanced, + advert_data, PowerMode::kBalanced, AdvertisingCallback{ .start_advertising_result = [&](BleOperationStatus status) { advertise_latch.CountDown(); @@ -172,7 +173,7 @@ TEST_P(BleTest, AdvertiseAndScan) { EXPECT_EQ(advertisements[0] .service_data.find(kPresenceServiceUuid) ->second.AsStringView(), - advert_data); + advert_data.content); env_.Stop(); } diff --git a/presence/implementation/scan_manager_test.cc b/presence/implementation/scan_manager_test.cc index e943804e..b1e9d585 100644 --- a/presence/implementation/scan_manager_test.cc +++ b/presence/implementation/scan_manager_test.cc @@ -21,6 +21,8 @@ #include #include +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" #include "gtest/gtest.h" #include "absl/random/random.h" #include "internal/platform/bluetooth_adapter.h" @@ -36,12 +38,39 @@ namespace nearby { namespace presence { namespace { -using BleOperationStatus = location::nearby::api::ble_v2::BleOperationStatus; +using BleOperationStatus = ::location::nearby::api::ble_v2::BleOperationStatus; +using AdvertisingSession = + ::location::nearby::api::ble_v2::BleMedium::AdvertisingSession; +using AdvertisingCallback = + ::location::nearby::api::ble_v2::BleMedium::AdvertisingCallback; class ScanManagerTest : public testing::Test { protected: void SetUp() override { env_.Start(); } void TearDown() override { env_.Stop(); } + + std::unique_ptr StartAdvertisingOn(Ble& ble) { + PresenceBroadcast::BroadcastSection section = { + .identity = internal::IDENTITY_TYPE_PUBLIC, + .extended_properties = extended_properties_, + .account_name = "Test account"}; + PresenceBroadcast presence_request = {.sections = {section}}; + BroadcastRequest input = {.tx_power = 30, .variant = presence_request}; + absl::StatusOr request = + BaseBroadcastRequest::Create(input); + EXPECT_OK(request); + AdvertisementFactory factory(&credential_manager_); + absl::StatusOr advertisement = + factory.CreateAdvertisement(request.value()); + EXPECT_OK(advertisement); + std::unique_ptr session = ble.StartAdvertising( + advertisement.value(), PowerMode::kLowPower, + AdvertisingCallback{ + .start_advertising_result = [](BleOperationStatus) {}}); + env_.Sync(); + return session; + } + std::vector identity_types_ = { nearby::internal::IdentityType::IDENTITY_TYPE_PUBLIC, }; @@ -64,54 +93,39 @@ class ScanManagerTest : public testing::Test { CredentialManagerImpl credential_manager_; location::nearby::MediumEnvironment& env_ = { location::nearby::MediumEnvironment::Instance()}; - location::nearby::api::ble_v2::AdvertiseParameters params_ = { - .tx_power_level = Ble::TxPowerLevel::kHigh, - .is_connectable = true, - }; location::nearby::CountDownLatch start_latch_{1}; location::nearby::CountDownLatch found_latch_{1}; + ScanCallback scanning_callback_ = {.start_scan_cb = + [this](Status status) { + NEARBY_LOGS(INFO) << "Scan started " + << status.Ok(); + if (status.Ok()) { + start_latch_.CountDown(); + } + }, + .on_discovered_cb = + [this](PresenceDevice pd) { + NEARBY_LOGS(INFO) << "Device found"; + found_latch_.CountDown(); + }}; }; TEST_F(ScanManagerTest, CanStartThenStopScanning) { Mediums mediums; ScanManager manager(mediums, credential_manager_); - ScanCallback scanning_callback = { - .start_scan_cb = - [this](Status status) { - if (status.Ok()) { - start_latch_.CountDown(); - } - }, - .on_discovered_cb = - [this](PresenceDevice pd) { found_latch_.CountDown(); }}; // Set up advertiser - // Create BroadcastRequest - PresenceBroadcast::BroadcastSection section = { - .identity = internal::IDENTITY_TYPE_PUBLIC, - .extended_properties = extended_properties_, - .account_name = "Test account"}; - PresenceBroadcast presence_request = {.sections = {section}}; - BroadcastRequest input = {.tx_power = 30, .variant = presence_request}; - - absl::StatusOr request = - BaseBroadcastRequest::Create(input); - AdvertisementFactory factory(&credential_manager_); - absl::StatusOr advertisement = - factory.CreateAdvertisement(request.ValueOrDie()); - location::nearby::BluetoothAdapter adapter2; - location::nearby::BleV2Medium ble2(adapter2); - ASSERT_TRUE(ble2.StartAdvertising(advertisement.ValueOrDie(), params_)); + location::nearby::BluetoothAdapter server_adapter; + Ble ble2(server_adapter); + std::unique_ptr advertising_session = + StartAdvertisingOn(ble2); // Start scanning ScanSession scan_session = - manager.StartScan(scan_request_, std::move(scanning_callback)); - // Ensure that we are in a good state. - env_.Sync(); + manager.StartScan(scan_request_, scanning_callback_); EXPECT_EQ(manager.ScanningCallbacksLengthForTest(), 1); - ASSERT_TRUE(ble2.IsValid()); ASSERT_TRUE(mediums.GetBle().IsAvailable()); - EXPECT_TRUE(start_latch_.Await(absl::Milliseconds(500)).result()); - EXPECT_TRUE(found_latch_.Await(absl::Milliseconds(1500)).result()); + EXPECT_TRUE(start_latch_.Await().Ok()); + EXPECT_TRUE(found_latch_.Await().Ok()); EXPECT_TRUE(scan_session.StopScan().Ok()); EXPECT_EQ(manager.ScanningCallbacksLengthForTest(), 0); } @@ -119,19 +133,11 @@ TEST_F(ScanManagerTest, CanStartThenStopScanning) { TEST_F(ScanManagerTest, CannotStopScanTwice) { Mediums mediums; ScanManager manager(mediums, credential_manager_); - ScanCallback scanning_callback = ScanCallback{ - .start_scan_cb = - [this](Status status) { - if (status.Ok()) { - start_latch_.CountDown(); - } - }, - }; - auto scan_session = - manager.StartScan(scan_request_, std::move(scanning_callback)); + auto scan_session = manager.StartScan(scan_request_, scanning_callback_); + NEARBY_LOGS(INFO) << "Start scan"; - EXPECT_TRUE(start_latch_.Await(absl::Milliseconds(1000)).result()); + EXPECT_TRUE(start_latch_.Await().Ok()); // Ensure that we have started scanning before we try to stop. env_.Sync(); NEARBY_LOGS(INFO) << "Stop scan"; @@ -143,32 +149,11 @@ TEST_F(ScanManagerTest, CannotStopScanTwice) { TEST_F(ScanManagerTest, TestNoFilter) { Mediums mediums; ScanManager manager(mediums, credential_manager_); - ScanCallback scanning_callback = { - .start_scan_cb = - [this](Status status) { - if (status.Ok()) { - start_latch_.CountDown(); - } - }, - .on_discovered_cb = - [this](PresenceDevice pd) { found_latch_.CountDown(); }}; // Set up advertiser - // Create BroadcastRequest - PresenceBroadcast::BroadcastSection section = { - .identity = internal::IDENTITY_TYPE_PUBLIC, - .extended_properties = {}, - .account_name = "Test account"}; - PresenceBroadcast presence_request = {.sections = {section}}; - BroadcastRequest input = {.tx_power = 30, .variant = presence_request}; - - absl::StatusOr request = - BaseBroadcastRequest::Create(input); - AdvertisementFactory factory(&credential_manager_); - absl::StatusOr advertisement = - factory.CreateAdvertisement(request.ValueOrDie()); - location::nearby::BluetoothAdapter adapter2; - location::nearby::BleV2Medium ble2(adapter2); - ASSERT_TRUE(ble2.StartAdvertising(advertisement.ValueOrDie(), params_)); + location::nearby::BluetoothAdapter server_adapter; + Ble ble2(server_adapter); + std::unique_ptr advertising_session = + StartAdvertisingOn(ble2); // Start scanning ScanRequest scan_request = { @@ -181,13 +166,12 @@ TEST_F(ScanManagerTest, TestNoFilter) { .scan_only_when_screen_on = true, }; ScanSession scan_session = - manager.StartScan(scan_request, std::move(scanning_callback)); + manager.StartScan(scan_request, scanning_callback_); EXPECT_EQ(manager.ScanningCallbacksLengthForTest(), 1); - ASSERT_TRUE(ble2.IsValid()); ASSERT_TRUE(mediums.GetBle().IsAvailable()); - EXPECT_TRUE(start_latch_.Await(absl::Milliseconds(500)).result()); - EXPECT_TRUE(found_latch_.Await(absl::Milliseconds(1500)).result()); + EXPECT_TRUE(start_latch_.Await().Ok()); + EXPECT_TRUE(found_latch_.Await().Ok()); EXPECT_TRUE(scan_session.StopScan().Ok()); EXPECT_EQ(manager.ScanningCallbacksLengthForTest(), 0); }