mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Add AdvertisementData struct.
Define and use an NP private AdvertisementData structure instead of the low level BleAdvertisementData, The APIs look cleaner this way. PiperOrigin-RevId: 486224840
This commit is contained in:
committed by
Copybara-Service
parent
de4e7a66dc
commit
951945dd5c
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<BleAdvertisementData> AdvertisementFactory::CreateAdvertisement(
|
||||
absl::StatusOr<AdvertisementData> AdvertisementFactory::CreateAdvertisement(
|
||||
const BaseBroadcastRequest& request) const {
|
||||
BleAdvertisementData advert = {};
|
||||
AdvertisementData advert = {};
|
||||
if (absl::holds_alternative<BaseBroadcastRequest::BasePresence>(
|
||||
request.variant)) {
|
||||
return CreateBaseNpAdvertisement(request);
|
||||
@@ -103,12 +103,11 @@ absl::StatusOr<BleAdvertisementData> AdvertisementFactory::CreateAdvertisement(
|
||||
return advert;
|
||||
}
|
||||
|
||||
absl::StatusOr<BleAdvertisementData>
|
||||
absl::StatusOr<AdvertisementData>
|
||||
AdvertisementFactory::CreateBaseNpAdvertisement(
|
||||
const BaseBroadcastRequest& request) const {
|
||||
const auto& presence =
|
||||
absl::get<BaseBroadcastRequest::BasePresence>(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
|
||||
|
||||
@@ -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<BleAdvertisementData> CreateAdvertisement(
|
||||
// Returns a BLE advertisement for given `request.
|
||||
absl::StatusOr<AdvertisementData> CreateAdvertisement(
|
||||
const BaseBroadcastRequest& request) const;
|
||||
|
||||
private:
|
||||
absl::StatusOr<BleAdvertisementData> CreateBaseNpAdvertisement(
|
||||
absl::StatusOr<AdvertisementData> CreateBaseNpAdvertisement(
|
||||
const BaseBroadcastRequest& request) const;
|
||||
|
||||
CredentialManager& credential_manager_;
|
||||
|
||||
@@ -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<BleAdvertisementData> result =
|
||||
absl::StatusOr<AdvertisementData> 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<BleAdvertisementData> result =
|
||||
absl::StatusOr<AdvertisementData> 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) {
|
||||
|
||||
@@ -18,6 +18,7 @@ cc_library(
|
||||
srcs = [
|
||||
],
|
||||
hdrs = [
|
||||
"advertisement_data.h",
|
||||
"ble.h",
|
||||
"mediums.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 <string>
|
||||
|
||||
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_
|
||||
@@ -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<AdvertisingSession> 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,
|
||||
|
||||
@@ -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<location::nearby::api::ble_v2::BleMedium::AdvertisingSession>
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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<AdvertisingSession> 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<BaseBroadcastRequest> request =
|
||||
BaseBroadcastRequest::Create(input);
|
||||
EXPECT_OK(request);
|
||||
AdvertisementFactory factory(&credential_manager_);
|
||||
absl::StatusOr<AdvertisementData> advertisement =
|
||||
factory.CreateAdvertisement(request.value());
|
||||
EXPECT_OK(advertisement);
|
||||
std::unique_ptr<AdvertisingSession> session = ble.StartAdvertising(
|
||||
advertisement.value(), PowerMode::kLowPower,
|
||||
AdvertisingCallback{
|
||||
.start_advertising_result = [](BleOperationStatus) {}});
|
||||
env_.Sync();
|
||||
return session;
|
||||
}
|
||||
|
||||
std::vector<nearby::internal::IdentityType> 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<BaseBroadcastRequest> request =
|
||||
BaseBroadcastRequest::Create(input);
|
||||
AdvertisementFactory factory(&credential_manager_);
|
||||
absl::StatusOr<BleAdvertisementData> 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<AdvertisingSession> 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<BaseBroadcastRequest> request =
|
||||
BaseBroadcastRequest::Create(input);
|
||||
AdvertisementFactory factory(&credential_manager_);
|
||||
absl::StatusOr<BleAdvertisementData> 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<AdvertisingSession> 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user