mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 07:36:10 -04:00
[NC]Read GATT data on device with BLE extended support
PiperOrigin-RevId: 797846587
This commit is contained in:
committed by
Copybara-Service
parent
6113d225e9
commit
adf211a891
@@ -141,6 +141,7 @@ cc_test(
|
||||
"//internal/platform:uuid",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation/g3", # buildcleaner: keep
|
||||
"//internal/test",
|
||||
"//proto/mediums:ble_frames_cc_proto",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
|
||||
@@ -59,6 +59,8 @@ namespace mediums {
|
||||
namespace {
|
||||
constexpr int kGattThreadCount = 1;
|
||||
constexpr absl::Duration kInstantLostAdvertisementTimeout = absl::Seconds(60);
|
||||
constexpr absl::Duration kExtendedAdvertisementHeaderDelay = absl::Seconds(3);
|
||||
constexpr absl::Duration kAdvertisementHeaderExpiry = absl::Seconds(15);
|
||||
} // namespace
|
||||
|
||||
DiscoveredPeripheralTracker::DiscoveredPeripheralTracker(
|
||||
@@ -127,6 +129,11 @@ void DiscoveredPeripheralTracker::StartTracking(
|
||||
.include_dct_advertisement = include_dct_advertisement,
|
||||
.pcp = pcp};
|
||||
|
||||
if (service_id_infos_.empty()) {
|
||||
medium_start_scanning_time_ = SystemClock::ElapsedRealtime();
|
||||
VLOG(1) << "Medium start scanning time: " << medium_start_scanning_time_;
|
||||
}
|
||||
|
||||
// Replace if key exists.
|
||||
service_id_infos_.insert_or_assign(service_id, std::move(service_id_info));
|
||||
|
||||
@@ -177,8 +184,7 @@ void DiscoveredPeripheralTracker::ProcessFoundBleAdvertisement(
|
||||
}
|
||||
|
||||
if (IsSkippableGattAdvertisement(advertisement_data)) {
|
||||
LOG(INFO)
|
||||
<< "Ignore GATT advertisement and wait for extended advertisement.";
|
||||
VLOG(1) << "Ignore GATT advertisement and wait for extended advertisement.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -330,8 +336,21 @@ bool DiscoveredPeripheralTracker::IsSkippableGattAdvertisement(
|
||||
BleAdvertisementHeader advertisement_header(
|
||||
ExtractAdvertisementHeaderBytes(advertisement_data));
|
||||
|
||||
return advertisement_header.IsValid() &&
|
||||
advertisement_header.IsSupportExtendedAdvertisement();
|
||||
if (is_read_gatt_for_extended_advertisement_enabled_) {
|
||||
if (!advertisement_header.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (advertisement_header.IsSupportExtendedAdvertisement() &&
|
||||
(SystemClock::ElapsedRealtime() - medium_start_scanning_time_) <
|
||||
kExtendedAdvertisementHeaderDelay) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return advertisement_header.IsValid() &&
|
||||
advertisement_header.IsSupportExtendedAdvertisement();
|
||||
}
|
||||
}
|
||||
|
||||
void DiscoveredPeripheralTracker::ClearGattAdvertisement(
|
||||
@@ -749,46 +768,67 @@ void DiscoveredPeripheralTracker::HandleAdvertisementHeader(
|
||||
}
|
||||
|
||||
// Determine whether or not we need to read a fresh GATT advertisement.
|
||||
if (ShouldReadRawAdvertisementFromServer(advertisement_header)) {
|
||||
// Determine whether or not we need to read a fresh GATT advertisement.
|
||||
if (is_fetching_in_thread_) {
|
||||
VLOG(1) << ": Handle GATT advertisement header with hash "
|
||||
<< absl::BytesToHexString(
|
||||
advertisement_header.GetAdvertisementHash().AsStringView())
|
||||
<< " in thread";
|
||||
if (is_fetching_in_thread_) {
|
||||
VLOG(1) << ": Handle GATT advertisement header with hash "
|
||||
<< absl::BytesToHexString(
|
||||
advertisement_header.GetAdvertisementHash().AsStringView())
|
||||
<< " in thread";
|
||||
|
||||
if (!fetching_advertisements_.insert(advertisement_header).second) {
|
||||
VLOG(1) << ": Ignore the advertisement header due to it "
|
||||
"is already in fetching.";
|
||||
return;
|
||||
}
|
||||
if (executor_ == nullptr) {
|
||||
// The situation happens when flag value changed
|
||||
executor_ = std::make_unique<MultiThreadExecutor>(kGattThreadCount);
|
||||
}
|
||||
|
||||
if (executor_ == nullptr) {
|
||||
// The situation happens when flag value changed
|
||||
executor_ = std::make_unique<MultiThreadExecutor>(kGattThreadCount);
|
||||
}
|
||||
if (!ShouldReadRawAdvertisementFromServer(advertisement_header)) {
|
||||
UpdateCommonStateForFoundBleAdvertisement(advertisement_header);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_read_gatt_for_extended_advertisement_enabled_) {
|
||||
{
|
||||
MutexLock lock(&task_mutex_);
|
||||
gatt_fetch_tasks_.push_back({
|
||||
.peripheral = peripheral,
|
||||
.advertisement_header = advertisement_header,
|
||||
.advertisement_fetcher = std::move(advertisement_fetcher),
|
||||
});
|
||||
cond_.Notify();
|
||||
if (is_read_gatt_for_extended_advertisement_enabled_) {
|
||||
MutexLock lock(&task_mutex_);
|
||||
if (advertisement_header.IsSupportExtendedAdvertisement() &&
|
||||
is_extended_advertisement_available_) {
|
||||
for (auto& item : gatt_extended_fetch_tasks_) {
|
||||
if (item.advertisement_header == advertisement_header) {
|
||||
item.scheduled_time = SystemClock::ElapsedRealtime();
|
||||
UpdateCommonStateForFoundBleAdvertisement(advertisement_header);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gatt_extended_fetch_tasks_.push_back({
|
||||
.peripheral = peripheral,
|
||||
.advertisement_header = advertisement_header,
|
||||
.advertisement_fetcher = std::move(advertisement_fetcher),
|
||||
.scheduled_time = SystemClock::ElapsedRealtime(),
|
||||
});
|
||||
} else {
|
||||
executor_->Execute([this, peripheral, advertisement_header,
|
||||
advertisement_fetcher =
|
||||
std::move(advertisement_fetcher)]() mutable {
|
||||
FetchRawAdvertisementsInThread(peripheral, advertisement_header,
|
||||
std::move(advertisement_fetcher));
|
||||
for (auto& item : gatt_fetch_tasks_) {
|
||||
if (item.advertisement_header == advertisement_header) {
|
||||
item.scheduled_time = SystemClock::ElapsedRealtime();
|
||||
UpdateCommonStateForFoundBleAdvertisement(advertisement_header);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gatt_fetch_tasks_.push_back({
|
||||
.peripheral = peripheral,
|
||||
.advertisement_header = advertisement_header,
|
||||
.advertisement_fetcher = std::move(advertisement_fetcher),
|
||||
.scheduled_time = SystemClock::ElapsedRealtime(),
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
cond_.Notify();
|
||||
} else {
|
||||
executor_->Execute(
|
||||
[this, peripheral, advertisement_header,
|
||||
advertisement_fetcher = std::move(advertisement_fetcher)]() mutable {
|
||||
FetchRawAdvertisementsInThread(peripheral, advertisement_header,
|
||||
std::move(advertisement_fetcher));
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (ShouldReadRawAdvertisementFromServer(advertisement_header)) {
|
||||
std::vector<const ByteArray*> gatt_advertisement_bytes_list =
|
||||
FetchRawAdvertisements(peripheral, advertisement_header,
|
||||
std::move(advertisement_fetcher));
|
||||
@@ -869,7 +909,7 @@ bool DiscoveredPeripheralTracker::ShouldReadRawAdvertisementFromServer(
|
||||
<< ", but we have already read its GATT advertisement.";
|
||||
return false;
|
||||
case AdvertisementReadResult::RetryStatus::kTooSoon:
|
||||
LOG(INFO)
|
||||
VLOG(1)
|
||||
<< "Received advertisement header with hash "
|
||||
<< absl::BytesToHexString(
|
||||
advertisement_header.GetAdvertisementHash().AsStringView())
|
||||
@@ -922,7 +962,10 @@ void DiscoveredPeripheralTracker::FetchRawAdvertisementsInThread(
|
||||
if (!IsInterestingAdvertisementHeader(advertisement_header)) {
|
||||
LOG(INFO) << ": Ignore to read raw advertisement from server due to it "
|
||||
"is not interesting header now.";
|
||||
fetching_advertisements_.erase(advertisement_header);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ShouldReadRawAdvertisementFromServer(advertisement_header)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -943,7 +986,6 @@ void DiscoveredPeripheralTracker::FetchRawAdvertisementsInThread(
|
||||
LOG(WARNING)
|
||||
<< ": Ignore the fetched GATT advertisement from server due to it "
|
||||
"is not interesting header now.";
|
||||
fetching_advertisements_.erase(advertisement_header);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -952,9 +994,9 @@ void DiscoveredPeripheralTracker::FetchRawAdvertisementsInThread(
|
||||
std::vector<const ByteArray*> gatt_advertisement_bytes_list =
|
||||
it.first->second->GetAdvertisements();
|
||||
|
||||
if (gatt_advertisement_bytes_list.empty() ||
|
||||
!IsInterestingAdvertisementHeader(advertisement_header)) {
|
||||
fetching_advertisements_.erase(advertisement_header);
|
||||
if (gatt_advertisement_bytes_list.empty()) {
|
||||
VLOG(1) << ": Ignore the fetched GATT advertisement from server due to "
|
||||
"it is empty.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -962,7 +1004,6 @@ void DiscoveredPeripheralTracker::FetchRawAdvertisementsInThread(
|
||||
gatt_advertisement_bytes_list,
|
||||
/*service_uuid=*/{});
|
||||
UpdateCommonStateForFoundBleAdvertisement(advertisement_header);
|
||||
fetching_advertisements_.erase(advertisement_header);
|
||||
VLOG(1) << ": Completed to handle GATT advertisement header with hash "
|
||||
<< absl::BytesToHexString(
|
||||
advertisement_header.GetAdvertisementHash().AsStringView())
|
||||
@@ -979,17 +1020,37 @@ void DiscoveredPeripheralTracker::GattFetchingLoop() {
|
||||
gatt_fetch_tasks_.clear();
|
||||
return;
|
||||
}
|
||||
while (gatt_fetch_tasks_.empty() && !shutting_down_) {
|
||||
while (gatt_fetch_tasks_.empty() && gatt_extended_fetch_tasks_.empty() &&
|
||||
!shutting_down_) {
|
||||
cond_.Wait();
|
||||
}
|
||||
|
||||
if (shutting_down_) {
|
||||
gatt_fetch_tasks_.clear();
|
||||
gatt_extended_fetch_tasks_.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
task = std::move(gatt_fetch_tasks_.front());
|
||||
gatt_fetch_tasks_.pop_front();
|
||||
// Non-extended advertisements are prioritized over extended
|
||||
// advertisements.
|
||||
if (!gatt_fetch_tasks_.empty()) {
|
||||
task = std::move(gatt_fetch_tasks_.front());
|
||||
gatt_fetch_tasks_.pop_front();
|
||||
} else if (!gatt_extended_fetch_tasks_.empty()) {
|
||||
task = std::move(gatt_extended_fetch_tasks_.front());
|
||||
gatt_extended_fetch_tasks_.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the task is expired.
|
||||
if (SystemClock::ElapsedRealtime() - task.scheduled_time >
|
||||
kAdvertisementHeaderExpiry) {
|
||||
VLOG(1) << "GATT advertisement with hash: "
|
||||
<< absl::BytesToHexString(
|
||||
task.advertisement_header.GetAdvertisementHash()
|
||||
.AsStringView())
|
||||
<< " is expired, skip to fetch raw advertisement.";
|
||||
continue;
|
||||
}
|
||||
|
||||
FetchRawAdvertisementsInThread(task.peripheral, task.advertisement_header,
|
||||
@@ -1001,7 +1062,7 @@ void DiscoveredPeripheralTracker::UpdateCommonStateForFoundBleAdvertisement(
|
||||
const BleAdvertisementHeader& advertisement_header) {
|
||||
const auto ga_it = gatt_advertisements_.find(advertisement_header);
|
||||
if (ga_it == gatt_advertisements_.end()) {
|
||||
LOG(INFO)
|
||||
VLOG(1)
|
||||
<< "No GATT advertisements found for advertisement header with hash "
|
||||
<< absl::BytesToHexString(
|
||||
advertisement_header.GetAdvertisementHash().AsStringView());
|
||||
|
||||
@@ -158,6 +158,7 @@ class DiscoveredPeripheralTracker {
|
||||
BleV2Peripheral peripheral;
|
||||
BleAdvertisementHeader advertisement_header;
|
||||
AdvertisementFetcher advertisement_fetcher;
|
||||
absl::Time scheduled_time;
|
||||
};
|
||||
|
||||
// Clears stale data from any previous sessions.
|
||||
@@ -309,6 +310,9 @@ class DiscoveredPeripheralTracker {
|
||||
bool is_read_gatt_for_extended_advertisement_enabled_ = true;
|
||||
bool is_extended_advertisement_available_;
|
||||
|
||||
absl::Time medium_start_scanning_time_ ABSL_GUARDED_BY(mutex_) =
|
||||
absl::InfiniteFuture();
|
||||
|
||||
// ------------ SERVICE ID MAPS ------------
|
||||
// Entries in these maps all follow the same lifecycle. Entries are added in
|
||||
// StartTracking, and removed in StopTracking.
|
||||
@@ -351,10 +355,6 @@ class DiscoveredPeripheralTracker {
|
||||
absl::flat_hash_map<BleAdvertisement, GattAdvertisementInfo>
|
||||
gatt_advertisement_infos_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
// Tracks the advertisements in GATT fetching.
|
||||
absl::flat_hash_set<BleAdvertisementHeader> fetching_advertisements_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
std::unique_ptr<MultiThreadExecutor> executor_ ABSL_GUARDED_BY(mutex_) =
|
||||
nullptr;
|
||||
|
||||
@@ -362,6 +362,8 @@ class DiscoveredPeripheralTracker {
|
||||
AtomicBoolean shutting_down_{false};
|
||||
ConditionVariable cond_{&task_mutex_};
|
||||
std::deque<GattFetchTask> gatt_fetch_tasks_ ABSL_GUARDED_BY(task_mutex_);
|
||||
std::deque<GattFetchTask> gatt_extended_fetch_tasks_
|
||||
ABSL_GUARDED_BY(task_mutex_);
|
||||
|
||||
// Maps an advertisement header's hash with the time it's reported lost.
|
||||
// Ignores subsequent discovery events for the same advertisement header.
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
@@ -51,6 +53,7 @@
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/mutex_lock.h"
|
||||
#include "internal/platform/uuid.h"
|
||||
#include "internal/test/fake_clock.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
@@ -66,6 +69,7 @@ constexpr absl::string_view kData = "\x04\x02\x00";
|
||||
constexpr absl::string_view kData2 = "\x07\x00\x07";
|
||||
constexpr absl::string_view kDeviceToken = "\x04\x20";
|
||||
constexpr absl::string_view kDeviceName = "device";
|
||||
constexpr absl::Duration kDefaultGattFetchDelay = absl::Milliseconds(200);
|
||||
|
||||
ByteArray CreateFastBleAdvertisement(const ByteArray& data,
|
||||
const ByteArray& device_token) {
|
||||
@@ -141,6 +145,24 @@ ByteArray CreateBleAdvertisementHeader(const ByteArray& advertisement_hash,
|
||||
service_ids);
|
||||
}
|
||||
|
||||
ByteArray CreateExtendedBleAdvertisementHeader(
|
||||
const ByteArray& advertisement_hash,
|
||||
std::vector<std::string>& service_ids) {
|
||||
BloomFilter service_id_bloom_filter(
|
||||
std::make_unique<BitSetImpl<
|
||||
BleAdvertisementHeader::kServiceIdBloomFilterByteLength>>());
|
||||
|
||||
for (const std::string& service_id : service_ids) {
|
||||
service_id_bloom_filter.Add(service_id);
|
||||
}
|
||||
|
||||
return ByteArray(BleAdvertisementHeader(
|
||||
BleAdvertisementHeader::Version::kV2,
|
||||
/*extended_advertisement=*/true,
|
||||
/*num_slots=*/service_ids.size(), ByteArray(service_id_bloom_filter),
|
||||
advertisement_hash, BleAdvertisementHeader::kDefaultPsmValue));
|
||||
}
|
||||
|
||||
ByteArray GenerateRandomAdvertisementHash() {
|
||||
ByteArray random_advertisement_hash = Utils::GenerateRandomBytes(
|
||||
BleAdvertisementHeader::kAdvertisementHashByteLength);
|
||||
@@ -179,13 +201,18 @@ class DiscoveredPeripheralTrackerTest
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableGattQueryInThread,
|
||||
std::get<0>(GetParam()));
|
||||
bool enable_read_gatt_for_extended_advertisement = std::get<1>(GetParam());
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableReadGattForExtendedAdvertisement,
|
||||
std::get<1>(GetParam()));
|
||||
MediumEnvironment::Instance().Start();
|
||||
enable_read_gatt_for_extended_advertisement);
|
||||
EnvironmentConfig config{
|
||||
.webrtc_enabled = false,
|
||||
.use_simulated_clock = enable_read_gatt_for_extended_advertisement};
|
||||
MediumEnvironment::Instance().Start(config);
|
||||
discovered_peripheral_tracker_ =
|
||||
std::make_unique<DiscoveredPeripheralTracker>();
|
||||
std::make_unique<DiscoveredPeripheralTracker>(
|
||||
enable_read_gatt_for_extended_advertisement);
|
||||
adapter_peripheral_ = std::make_unique<BluetoothAdapter>();
|
||||
adapter_central_ = std::make_unique<BluetoothAdapter>();
|
||||
ble_peripheral_ = std::make_unique<BleV2Medium>(*adapter_peripheral_);
|
||||
@@ -216,6 +243,20 @@ class DiscoveredPeripheralTrackerTest
|
||||
GetAdvertisementFetcher(fetch_latch, advertisement_bytes_list));
|
||||
}
|
||||
|
||||
// Simulates to see an extended advertisement, which don't need to fetch
|
||||
// advertisement from GATT.
|
||||
void FindExtendedAdvertisement(
|
||||
const api::ble_v2::BleAdvertisementData& advertisement_data,
|
||||
CountDownLatch& fetch_latch) {
|
||||
BleV2Peripheral peripheral = CreateBlePeripheral();
|
||||
DiscoveredPeripheralTracker::AdvertisementFetcher placeholder_fetcher =
|
||||
[](BleV2Peripheral, int, int, const std::vector<std::string>&,
|
||||
mediums::AdvertisementReadResult&) {};
|
||||
discovered_peripheral_tracker_->ProcessFoundBleAdvertisement(
|
||||
peripheral, advertisement_data, std::move(placeholder_fetcher));
|
||||
fetch_latch.CountDown();
|
||||
}
|
||||
|
||||
// Simulates to see a regular advertisement.
|
||||
void FindAdvertisement(
|
||||
const api::ble_v2::BleAdvertisementData& advertisement_data,
|
||||
@@ -228,15 +269,16 @@ class DiscoveredPeripheralTrackerTest
|
||||
GetAdvertisementFetcher(fetch_latch, advertisement_bytes_list));
|
||||
}
|
||||
|
||||
void FindAdvertisementWithSlowFetcher(
|
||||
void FindAdvertisementWithDelay(
|
||||
const api::ble_v2::BleAdvertisementData& advertisement_data,
|
||||
const std::vector<ByteArray>& advertisement_bytes_list,
|
||||
CountDownLatch& fetch_latch) {
|
||||
CountDownLatch& fetch_latch, absl::Duration delay) {
|
||||
BleV2Peripheral peripheral = CreateBlePeripheral();
|
||||
|
||||
discovered_peripheral_tracker_->ProcessFoundBleAdvertisement(
|
||||
peripheral, advertisement_data,
|
||||
GetSlowAdvertisementFetcher(fetch_latch, advertisement_bytes_list));
|
||||
GetAdvertisementFetcherWithDelay(fetch_latch, advertisement_bytes_list,
|
||||
delay));
|
||||
}
|
||||
|
||||
int GetFetchAdvertisementCallbackCount() const {
|
||||
@@ -278,10 +320,12 @@ class DiscoveredPeripheralTrackerTest
|
||||
};
|
||||
}
|
||||
|
||||
DiscoveredPeripheralTracker::AdvertisementFetcher GetSlowAdvertisementFetcher(
|
||||
DiscoveredPeripheralTracker::AdvertisementFetcher
|
||||
GetAdvertisementFetcherWithDelay(
|
||||
CountDownLatch& fetch_latch,
|
||||
const std::vector<ByteArray>& advertisement_bytes_list) {
|
||||
return [this, &fetch_latch, advertisement_bytes_list](
|
||||
const std::vector<ByteArray>& advertisement_bytes_list,
|
||||
absl::Duration delay) {
|
||||
return [this, &fetch_latch, advertisement_bytes_list, delay](
|
||||
BleV2Peripheral peripheral, int num_slots, int psm,
|
||||
const std::vector<std::string>& interesting_service_ids,
|
||||
mediums::AdvertisementReadResult& advertisement_read_result) {
|
||||
@@ -289,7 +333,7 @@ class DiscoveredPeripheralTrackerTest
|
||||
fetch_count_++;
|
||||
int slot = 0;
|
||||
// In real environment, the GATT fetch may run about 3-5 seconds.
|
||||
absl::SleepFor(absl::Milliseconds(200));
|
||||
absl::SleepFor(delay);
|
||||
for (const auto& advertisement_bytes : advertisement_bytes_list) {
|
||||
advertisement_read_result.AddAdvertisement(slot++, advertisement_bytes);
|
||||
}
|
||||
@@ -1539,11 +1583,11 @@ TEST_P(DiscoveredPeripheralTrackerTest, FetchGattAdvertisementInThread) {
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
|
||||
}
|
||||
|
||||
FindAdvertisementWithSlowFetcher(advertisement_data, {advertisement_bytes},
|
||||
fetch_latch);
|
||||
FindAdvertisementWithDelay(advertisement_data, {advertisement_bytes},
|
||||
fetch_latch, kDefaultGattFetchDelay);
|
||||
|
||||
// We should receive a client callback of a peripheral discovery.
|
||||
fetch_latch.Await(kWaitDuration);
|
||||
EXPECT_TRUE(fetch_latch.Await(kWaitDuration).ok());
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 1);
|
||||
}
|
||||
@@ -1586,13 +1630,13 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
|
||||
}
|
||||
|
||||
FindAdvertisementWithSlowFetcher(advertisement_data, {advertisement_bytes},
|
||||
fetch_latch);
|
||||
FindAdvertisementWithDelay(advertisement_data, {advertisement_bytes},
|
||||
fetch_latch, kDefaultGattFetchDelay);
|
||||
|
||||
// We should receive a client callback of a peripheral discovery.
|
||||
absl::SleepFor(absl::Milliseconds(20));
|
||||
discovered_peripheral_tracker_->StopTracking(std::string(kServiceIdA));
|
||||
fetch_latch.Await(kWaitDuration);
|
||||
EXPECT_TRUE(fetch_latch.Await(kWaitDuration).ok());
|
||||
EXPECT_FALSE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 1);
|
||||
}
|
||||
@@ -1638,8 +1682,8 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
|
||||
}
|
||||
|
||||
FindAdvertisementWithSlowFetcher(advertisement_data, {advertisement_bytes},
|
||||
fetch_latch);
|
||||
FindAdvertisementWithDelay(advertisement_data, {advertisement_bytes},
|
||||
fetch_latch, kDefaultGattFetchDelay);
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data_2{};
|
||||
if (!advertisement_header_bytes_2.Empty()) {
|
||||
@@ -1647,13 +1691,331 @@ TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes_2});
|
||||
}
|
||||
|
||||
FindAdvertisementWithSlowFetcher(advertisement_data_2,
|
||||
{advertisement_bytes_2}, fetch_latch);
|
||||
FindAdvertisementWithDelay(advertisement_data_2, {advertisement_bytes_2},
|
||||
fetch_latch, kDefaultGattFetchDelay);
|
||||
|
||||
// We should receive a client callback of a peripheral discovery.
|
||||
EXPECT_TRUE(fetch_latch.Await(kWaitDuration).ok());
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 2);
|
||||
}
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
GattAdvertisementGotEarlierThanExtendedAdvertisement) {
|
||||
if (!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableGattQueryInThread) ||
|
||||
!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableReadGattForExtendedAdvertisement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_bytes =
|
||||
CreateExtendedBleAdvertisementHeader(advertisement_hash, service_ids);
|
||||
ByteArray advertisement_bytes = CreateBleAdvertisement(
|
||||
std::string(kServiceIdA), ByteArray(std::string(kData)),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
CountDownLatch found_latch(1);
|
||||
CountDownLatch fetch_latch(2);
|
||||
|
||||
discovered_peripheral_tracker_->StartTracking(
|
||||
std::string(kServiceIdA), false, Pcp::kP2pPointToPoint,
|
||||
{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](BleV2Peripheral peripheral,
|
||||
const std::string& service_id,
|
||||
const ByteArray& advertisement_bytes,
|
||||
bool fast_advertisement) {
|
||||
EXPECT_EQ(advertisement_bytes, ByteArray(std::string(kData)));
|
||||
EXPECT_FALSE(fast_advertisement);
|
||||
found_latch.CountDown();
|
||||
},
|
||||
},
|
||||
bleutils::kCopresenceServiceUuid);
|
||||
|
||||
// 1. First receive a GATT advertisement data, it should be skipped.
|
||||
api::ble_v2::BleAdvertisementData advertisement_data{};
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
|
||||
}
|
||||
|
||||
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
|
||||
|
||||
// 2. Receive extended advertisement data first.
|
||||
api::ble_v2::BleAdvertisementData extended_advertisement_data{};
|
||||
extended_advertisement_data.is_extended_advertisement = true;
|
||||
extended_advertisement_data.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_bytes});
|
||||
|
||||
FindExtendedAdvertisement(extended_advertisement_data, fetch_latch);
|
||||
|
||||
// We should receive a client callback of a peripheral discovery.
|
||||
fetch_latch.Await(kWaitDuration);
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 2);
|
||||
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 0);
|
||||
}
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
OnlyGattAdvertisementReceivedOnDeviceWithExtended) {
|
||||
if (!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableGattQueryInThread) ||
|
||||
!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableReadGattForExtendedAdvertisement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_bytes =
|
||||
CreateExtendedBleAdvertisementHeader(advertisement_hash, service_ids);
|
||||
ByteArray advertisement_bytes = CreateBleAdvertisement(
|
||||
std::string(kServiceIdA), ByteArray(std::string(kData)),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
CountDownLatch found_latch(1);
|
||||
CountDownLatch fetch_latch(2);
|
||||
|
||||
discovered_peripheral_tracker_->StartTracking(
|
||||
std::string(kServiceIdA), false, Pcp::kP2pPointToPoint,
|
||||
{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](BleV2Peripheral peripheral,
|
||||
const std::string& service_id,
|
||||
const ByteArray& advertisement_bytes,
|
||||
bool fast_advertisement) {
|
||||
EXPECT_EQ(advertisement_bytes, ByteArray(std::string(kData)));
|
||||
EXPECT_FALSE(fast_advertisement);
|
||||
found_latch.CountDown();
|
||||
},
|
||||
},
|
||||
bleutils::kCopresenceServiceUuid);
|
||||
|
||||
// 1. First receive a GATT advertisement data, it should be skipped.
|
||||
api::ble_v2::BleAdvertisementData advertisement_data{};
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
|
||||
}
|
||||
|
||||
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
|
||||
|
||||
// 2. Receive GATT advertisement data again after 4 seconds, it should access
|
||||
// GATT server.
|
||||
(*fake_clock)->FastForward(absl::Seconds(4));
|
||||
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
|
||||
|
||||
// We should receive a client callback of a peripheral discovery.
|
||||
fetch_latch.Await(kWaitDuration);
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 1);
|
||||
}
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest, SkipExpiredGattAdvertisement) {
|
||||
if (!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableGattQueryInThread) ||
|
||||
!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableReadGattForExtendedAdvertisement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_bytes =
|
||||
CreateExtendedBleAdvertisementHeader(advertisement_hash, service_ids);
|
||||
ByteArray advertisement_bytes = CreateBleAdvertisement(
|
||||
std::string(kServiceIdA), ByteArray(std::string(kData)),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
CountDownLatch found_latch(1);
|
||||
CountDownLatch fetch_latch(2);
|
||||
|
||||
discovered_peripheral_tracker_->StartTracking(
|
||||
std::string(kServiceIdA), false, Pcp::kP2pPointToPoint,
|
||||
{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](BleV2Peripheral peripheral,
|
||||
const std::string& service_id,
|
||||
const ByteArray& advertisement_bytes,
|
||||
bool fast_advertisement) {
|
||||
EXPECT_EQ(advertisement_bytes, ByteArray(std::string(kData)));
|
||||
EXPECT_FALSE(fast_advertisement);
|
||||
found_latch.CountDown();
|
||||
},
|
||||
},
|
||||
bleutils::kCopresenceServiceUuid);
|
||||
|
||||
// 1. First receive a GATT advertisement data, it should be skipped.
|
||||
api::ble_v2::BleAdvertisementData advertisement_data{};
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
|
||||
}
|
||||
|
||||
FindAdvertisementWithDelay(advertisement_data, {advertisement_bytes},
|
||||
fetch_latch, kDefaultGattFetchDelay);
|
||||
|
||||
// 2. The GATT advertisement will be expired after 20 seconds.
|
||||
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
|
||||
(*fake_clock)->FastForward(absl::Seconds(20));
|
||||
|
||||
// We should receive a client callback of a peripheral discovery.
|
||||
fetch_latch.Await(kWaitDuration);
|
||||
EXPECT_FALSE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 0);
|
||||
}
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
DiscoveredOnceWhenGattAndExtendedAdvertisementReceived) {
|
||||
if (!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableGattQueryInThread) ||
|
||||
!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableReadGattForExtendedAdvertisement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_bytes =
|
||||
CreateExtendedBleAdvertisementHeader(advertisement_hash, service_ids);
|
||||
ByteArray advertisement_bytes = CreateBleAdvertisement(
|
||||
std::string(kServiceIdA), ByteArray(std::string(kData)),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
CountDownLatch found_latch(1);
|
||||
CountDownLatch fetch_latch(2);
|
||||
std::atomic<int> callback_count = 0;
|
||||
|
||||
discovered_peripheral_tracker_->StartTracking(
|
||||
std::string(kServiceIdA), false, Pcp::kP2pPointToPoint,
|
||||
{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch, &callback_count](
|
||||
BleV2Peripheral peripheral, const std::string& service_id,
|
||||
const ByteArray& advertisement_bytes,
|
||||
bool fast_advertisement) {
|
||||
++callback_count;
|
||||
found_latch.CountDown();
|
||||
},
|
||||
},
|
||||
bleutils::kCopresenceServiceUuid);
|
||||
(*fake_clock)->FastForward(absl::Seconds(4));
|
||||
|
||||
// 1. Received extended advertisement.
|
||||
api::ble_v2::BleAdvertisementData extended_advertisement_data{};
|
||||
extended_advertisement_data.is_extended_advertisement = true;
|
||||
extended_advertisement_data.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_bytes});
|
||||
|
||||
FindExtendedAdvertisement(extended_advertisement_data, fetch_latch);
|
||||
|
||||
// 2. Received GATT advertisement.
|
||||
api::ble_v2::BleAdvertisementData advertisement_data{};
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
|
||||
}
|
||||
|
||||
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
|
||||
|
||||
EXPECT_TRUE(fetch_latch.Await(kWaitDuration).ok());
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 1);
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
}
|
||||
|
||||
TEST_P(DiscoveredPeripheralTrackerTest,
|
||||
FindGattAdvertisementInHigherPriorityThanExtendedGattAdvertisement) {
|
||||
if (!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableGattQueryInThread) ||
|
||||
!NearbyFlags::GetInstance().GetBoolFlag(
|
||||
config_package_nearby::nearby_connections_feature::
|
||||
kEnableReadGattForExtendedAdvertisement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::optional<FakeClock*> fake_clock =
|
||||
MediumEnvironment::Instance().GetSimulatedClock();
|
||||
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
|
||||
ByteArray advertisement_hash_a = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_a =
|
||||
CreateBleAdvertisementHeader(advertisement_hash_a, service_ids);
|
||||
ByteArray advertisement_a = CreateBleAdvertisement(
|
||||
std::string(kServiceIdA), ByteArray(std::string("advertisement_a")),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
ByteArray advertisement_hash_b = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_b =
|
||||
CreateExtendedBleAdvertisementHeader(advertisement_hash_b, service_ids);
|
||||
ByteArray advertisement_b = CreateBleAdvertisement(
|
||||
std::string(kServiceIdA), ByteArray(std::string("advertisement_b")),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
ByteArray advertisement_hash_c = GenerateRandomAdvertisementHash();
|
||||
ByteArray advertisement_header_c =
|
||||
CreateBleAdvertisementHeader(advertisement_hash_c, service_ids);
|
||||
ByteArray advertisement_c = CreateBleAdvertisement(
|
||||
std::string(kServiceIdA), ByteArray(std::string("advertisement_c")),
|
||||
ByteArray(std::string(kDeviceToken)));
|
||||
CountDownLatch found_latch(3);
|
||||
CountDownLatch fetch_latch(3);
|
||||
std::vector<std::string> discovered_peripheral_order;
|
||||
|
||||
discovered_peripheral_tracker_->StartTracking(
|
||||
std::string(kServiceIdA), false, Pcp::kP2pPointToPoint,
|
||||
{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch, &discovered_peripheral_order](
|
||||
BleV2Peripheral peripheral, const std::string& service_id,
|
||||
const ByteArray& advertisement_bytes,
|
||||
bool fast_advertisement) {
|
||||
discovered_peripheral_order.push_back(
|
||||
std::string(advertisement_bytes));
|
||||
found_latch.CountDown();
|
||||
},
|
||||
},
|
||||
bleutils::kCopresenceServiceUuid);
|
||||
(*fake_clock)->FastForward(absl::Seconds(4));
|
||||
|
||||
// 1. Find peripheral A with GATT advertisement.
|
||||
api::ble_v2::BleAdvertisementData advertisement_data_a{};
|
||||
advertisement_data_a.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_a});
|
||||
FindAdvertisementWithDelay(advertisement_data_a, {advertisement_a},
|
||||
fetch_latch, kDefaultGattFetchDelay);
|
||||
|
||||
// 2. Find peripheral B with extended advertisement.
|
||||
api::ble_v2::BleAdvertisementData advertisement_data_b{};
|
||||
advertisement_data_b.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_b});
|
||||
FindAdvertisement(advertisement_data_b, {advertisement_b}, fetch_latch);
|
||||
|
||||
// 3. Find peripheral C with GATT advertisement.
|
||||
api::ble_v2::BleAdvertisementData advertisement_data_c{};
|
||||
advertisement_data_c.service_data.insert(
|
||||
{bleutils::kCopresenceServiceUuid, advertisement_header_c});
|
||||
FindAdvertisement(advertisement_data_c, {advertisement_c}, fetch_latch);
|
||||
|
||||
EXPECT_TRUE(fetch_latch.Await(kWaitDuration).ok());
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
ASSERT_EQ(discovered_peripheral_order.size(), 3);
|
||||
EXPECT_EQ(discovered_peripheral_order[0], "advertisement_a");
|
||||
EXPECT_EQ(discovered_peripheral_order[1], "advertisement_c");
|
||||
EXPECT_EQ(discovered_peripheral_order[2], "advertisement_b");
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
||||
Reference in New Issue
Block a user