mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Implement scanner for fast pair subsequent pairing
PiperOrigin-RevId: 548841808
This commit is contained in:
committed by
Copybara-Service
parent
7899d18907
commit
99053e4df3
@@ -97,6 +97,14 @@ class FastPairDevice {
|
||||
return ble_address_;
|
||||
}
|
||||
|
||||
void SetShowUiNotification(bool should_show_ui_notification) {
|
||||
should_show_ui_notification_ = should_show_ui_notification;
|
||||
}
|
||||
|
||||
std::optional<bool> ShouldShowUiNotification() const {
|
||||
return should_show_ui_notification_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string model_id_;
|
||||
|
||||
@@ -126,6 +134,7 @@ class FastPairDevice {
|
||||
AccountKey account_key_;
|
||||
|
||||
std::optional<DeviceMetadata> metadata_;
|
||||
std::optional<bool> should_show_ui_notification_;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const FastPairDevice& device);
|
||||
|
||||
@@ -94,6 +94,10 @@ Mediator::Mediator(
|
||||
|
||||
void Mediator::OnDeviceFound(FastPairDevice& device) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": " << device;
|
||||
if (device.ShouldShowUiNotification().value_or(false)) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Ignoring because show UI flag is false";
|
||||
return;
|
||||
}
|
||||
if (IsDeviceCurrentlyShowingNotification(device)) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Extending notification for re-discovered device="
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
#include "fastpair/repository/fake_fast_pair_repository.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "fastpair/common/account_key.h"
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "fastpair/proto/fastpair_rpcs.proto.h"
|
||||
|
||||
@@ -36,16 +38,32 @@ void FakeFastPairRepository::ClearFakeMetadata(absl::string_view hex_model_id) {
|
||||
data_.erase(hex_model_id);
|
||||
}
|
||||
|
||||
void FakeFastPairRepository::SetResultOfCheckIfAssociatedWithCurrentAccount(
|
||||
std::optional<AccountKey> account_key,
|
||||
std::optional<absl::string_view> model_id) {
|
||||
account_key_ = std::move(account_key);
|
||||
model_id_ = std::move(model_id);
|
||||
}
|
||||
|
||||
void FakeFastPairRepository::GetDeviceMetadata(
|
||||
absl::string_view hex_model_id, DeviceMetadataCallback callback) {
|
||||
executor_.Execute([callback = std::move(callback), this,
|
||||
executor_.Execute([this, callback = std::move(callback),
|
||||
hex_model_id = std::string(hex_model_id)]() mutable {
|
||||
if (data_.contains(hex_model_id)) {
|
||||
callback(*data_[hex_model_id]);
|
||||
std::move(callback)(*data_[hex_model_id]);
|
||||
} else {
|
||||
std::move(callback)(std::nullopt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FakeFastPairRepository::CheckIfAssociatedWithCurrentAccount(
|
||||
AccountKeyFilter& account_key_filter, CheckAccountKeysCallback callback) {
|
||||
executor_.Execute([this, callback = std::move(callback)]() mutable {
|
||||
std::move(callback)(account_key_, model_id_);
|
||||
});
|
||||
}
|
||||
|
||||
std::unique_ptr<FakeFastPairRepository> FakeFastPairRepository::Create(
|
||||
absl::string_view model_id, absl::string_view public_anti_spoof_key) {
|
||||
proto::Device metadata;
|
||||
@@ -64,6 +82,5 @@ std::unique_ptr<FakeFastPairRepository> FakeFastPairRepository::Create(
|
||||
repository->SetFakeMetadata(model_id, metadata);
|
||||
return repository;
|
||||
}
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "fastpair/common/account_key.h"
|
||||
#include "fastpair/common/device_metadata.h"
|
||||
#include "fastpair/repository/fast_pair_repository.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
@@ -39,6 +41,10 @@ class FakeFastPairRepository : public FastPairRepository {
|
||||
void SetFakeMetadata(absl::string_view hex_model_id, proto::Device metadata);
|
||||
void ClearFakeMetadata(absl::string_view hex_model_id);
|
||||
|
||||
void SetResultOfCheckIfAssociatedWithCurrentAccount(
|
||||
std::optional<AccountKey> account_key,
|
||||
std::optional<absl::string_view> model_id);
|
||||
|
||||
// FastPairRepository::
|
||||
void AddObserver(Observer* observer) override{};
|
||||
void RemoveObserver(Observer* observer) override{};
|
||||
@@ -58,10 +64,14 @@ class FakeFastPairRepository : public FastPairRepository {
|
||||
|
||||
void CheckIfAssociatedWithCurrentAccount(
|
||||
AccountKeyFilter& account_key_filter,
|
||||
CheckAccountKeysCallback callback) override{};
|
||||
CheckAccountKeysCallback callback) override;
|
||||
|
||||
private:
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<DeviceMetadata>> data_;
|
||||
|
||||
// Results of CheckIfAssociatedWithCurrentAccount
|
||||
std::optional<AccountKey> account_key_;
|
||||
std::optional<absl::string_view> model_id_;
|
||||
SingleThreadExecutor executor_;
|
||||
};
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -69,6 +69,7 @@ cc_test(
|
||||
"//fastpair/internal/mediums",
|
||||
"//fastpair/proto:fastpair_cc_proto",
|
||||
"//fastpair/repository:test_support",
|
||||
"//fastpair/testing",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
|
||||
@@ -18,11 +18,13 @@ cc_library(
|
||||
name = "scanning",
|
||||
srcs = [
|
||||
"fast_pair_discoverable_scanner_impl.cc",
|
||||
"fast_pair_non_discoverable_scanner.cc",
|
||||
"fast_pair_scanner_impl.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"fast_pair_discoverable_scanner.h",
|
||||
"fast_pair_discoverable_scanner_impl.h",
|
||||
"fast_pair_non_discoverable_scanner.h",
|
||||
"fast_pair_scanner.h",
|
||||
"fast_pair_scanner_impl.h",
|
||||
],
|
||||
@@ -112,3 +114,22 @@ cc_test(
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "fast_pair_non_discoverable_scanner_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"fast_pair_non_discoverable_scanner_test.cc",
|
||||
],
|
||||
shard_count = 16,
|
||||
deps = [
|
||||
":scanning",
|
||||
":test_support",
|
||||
"//fastpair/common",
|
||||
"//fastpair/repository:test_support",
|
||||
"//fastpair/testing",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
// Copyright 2023 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 "fastpair/scanning/fastpair/fast_pair_non_discoverable_scanner.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "fastpair/common/fast_pair_device.h"
|
||||
#include "fastpair/common/non_discoverable_advertisement.h"
|
||||
#include "fastpair/dataparser/fast_pair_data_parser.h"
|
||||
#include "fastpair/repository/fast_pair_repository.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
// static
|
||||
FastPairNonDiscoverableScanner::Factory*
|
||||
FastPairNonDiscoverableScanner::Factory::g_test_factory_ = nullptr;
|
||||
|
||||
// static
|
||||
std::unique_ptr<FastPairNonDiscoverableScanner>
|
||||
FastPairNonDiscoverableScanner::Factory::Create(
|
||||
FastPairScanner& scanner, NonDiscoverableScannerCallback found_callback,
|
||||
NonDiscoverableScannerCallback lost_callback,
|
||||
SingleThreadExecutor* executor,
|
||||
FastPairDeviceRepository* device_repository) {
|
||||
if (g_test_factory_) {
|
||||
return g_test_factory_->CreateInstance(scanner, std::move(found_callback),
|
||||
std::move(lost_callback), executor,
|
||||
device_repository);
|
||||
}
|
||||
|
||||
return std::make_unique<FastPairNonDiscoverableScanner>(
|
||||
scanner, std::move(found_callback), std::move(lost_callback), executor,
|
||||
device_repository);
|
||||
}
|
||||
|
||||
// static
|
||||
void FastPairNonDiscoverableScanner::Factory::SetFactoryForTesting(
|
||||
Factory* g_test_factory) {
|
||||
g_test_factory_ = g_test_factory;
|
||||
}
|
||||
|
||||
FastPairNonDiscoverableScanner::FastPairNonDiscoverableScanner(
|
||||
FastPairScanner& scanner, NonDiscoverableScannerCallback found_callback,
|
||||
NonDiscoverableScannerCallback lost_callback,
|
||||
SingleThreadExecutor* executor, FastPairDeviceRepository* device_repository)
|
||||
: scanner_(scanner),
|
||||
found_callback_(std::move(found_callback)),
|
||||
lost_callback_(std::move(lost_callback)),
|
||||
executor_(executor),
|
||||
device_repository_(device_repository) {
|
||||
scanner_.AddObserver(this);
|
||||
}
|
||||
|
||||
FastPairNonDiscoverableScanner::~FastPairNonDiscoverableScanner() {
|
||||
scanner_.RemoveObserver(this);
|
||||
}
|
||||
|
||||
void FastPairNonDiscoverableScanner::OnDeviceFound(
|
||||
const BlePeripheral& peripheral) {
|
||||
std::string fast_pair_service_data =
|
||||
peripheral.GetAdvertisementBytes(kServiceId).string_data();
|
||||
if (fast_pair_service_data.empty()) {
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": Device doesn't have any Fast Pair Service Data.";
|
||||
return;
|
||||
}
|
||||
executor_->Execute(
|
||||
"device-found",
|
||||
[this, fast_pair_service_data = std::move(fast_pair_service_data),
|
||||
address =
|
||||
peripheral.GetName()]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Attempting to parse advertisement.";
|
||||
FastPairDataParser::ParseNotDiscoverableAdvertisement(
|
||||
fast_pair_service_data, address,
|
||||
[&](std::optional<NonDiscoverableAdvertisement> advertisement) {
|
||||
OnAdvertisementParsed(address, advertisement);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairNonDiscoverableScanner::OnAdvertisementParsed(
|
||||
absl::string_view address,
|
||||
std::optional<NonDiscoverableAdvertisement> advertisement) {
|
||||
if (!advertisement.has_value()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__ << ": Returning early because no advertisement was parsed.";
|
||||
return;
|
||||
}
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__
|
||||
<< ": Attempting to check if device is associated with current account.";
|
||||
AccountKeyFilter account_filter(advertisement.value());
|
||||
FastPairRepository::Get()->CheckIfAssociatedWithCurrentAccount(
|
||||
account_filter, [&, address = std::string(address),
|
||||
advertisement = std::move(advertisement)](
|
||||
std::optional<AccountKey> account_key,
|
||||
std::optional<absl::string_view> model_id) {
|
||||
OnAccountKeyFilterCheckResult(address, advertisement, account_key,
|
||||
model_id);
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairNonDiscoverableScanner::OnAccountKeyFilterCheckResult(
|
||||
absl::string_view address,
|
||||
std::optional<NonDiscoverableAdvertisement> advertisement,
|
||||
std::optional<AccountKey> account_key,
|
||||
std::optional<absl::string_view> model_id) {
|
||||
if (!account_key.has_value() || !model_id.has_value()) {
|
||||
return;
|
||||
}
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Attempting to get device metadata.";
|
||||
FastPairRepository::Get()->GetDeviceMetadata(
|
||||
model_id.value(),
|
||||
[&, address = std::string(address),
|
||||
advertisement = std::move(advertisement), model_id = model_id.value(),
|
||||
account_key =
|
||||
account_key.value()](std::optional<DeviceMetadata> device_metadata) {
|
||||
OnDeviceMetadataRetrieved(address, advertisement, model_id, account_key,
|
||||
device_metadata);
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairNonDiscoverableScanner::OnDeviceMetadataRetrieved(
|
||||
absl::string_view address,
|
||||
std::optional<NonDiscoverableAdvertisement> advertisement,
|
||||
absl::string_view model_id, AccountKey account_key,
|
||||
std::optional<DeviceMetadata> device_metadata) {
|
||||
if (!device_metadata.has_value()) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": Failed to get device metadata";
|
||||
return;
|
||||
}
|
||||
|
||||
auto fast_pair_device = std::make_unique<FastPairDevice>(
|
||||
model_id, address, Protocol::kFastPairSubsequentPairing);
|
||||
fast_pair_device->SetAccountKey(account_key);
|
||||
fast_pair_device->SetMetadata(device_metadata.value());
|
||||
fast_pair_device->SetShowUiNotification(
|
||||
advertisement->type == NonDiscoverableAdvertisement::Type::kShowUi);
|
||||
executor_->Execute(
|
||||
"add-device",
|
||||
[this, fast_pair_device = std::move(fast_pair_device)]()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) mutable {
|
||||
FastPairDevice* device =
|
||||
device_repository_->AddDevice(std::move(fast_pair_device));
|
||||
NotifyDeviceFound(*device);
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairNonDiscoverableScanner::NotifyDeviceFound(FastPairDevice& device) {
|
||||
NEARBY_LOGS(VERBOSE) << "Notify Device found:"
|
||||
<< "BluetoothAddress = " << device.GetBleAddress()
|
||||
<< ", Model id = " << device.GetModelId();
|
||||
found_callback_(device);
|
||||
}
|
||||
|
||||
void FastPairNonDiscoverableScanner::OnDeviceLost(
|
||||
const BlePeripheral& peripheral) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Running lost callback";
|
||||
executor_->Execute("device-lost",
|
||||
[this, address = peripheral.GetName()]()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) {
|
||||
auto opt_device =
|
||||
device_repository_->FindDevice(address);
|
||||
|
||||
// Don't invoke callback if we didn't notify this
|
||||
// device.
|
||||
if (!opt_device.has_value()) return;
|
||||
FastPairDevice* device = opt_device.value();
|
||||
lost_callback_(*device);
|
||||
device_repository_->RemoveDevice(device);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright 2023 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_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_NON_DISCOVERABLE_SCANNER_H_
|
||||
#define THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_NON_DISCOVERABLE_SCANNER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "fastpair/common/fast_pair_device.h"
|
||||
#include "fastpair/common/non_discoverable_advertisement.h"
|
||||
#include "fastpair/repository/fast_pair_device_repository.h"
|
||||
#include "fastpair/scanning/fastpair/fast_pair_scanner.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
using NonDiscoverableScannerCallback =
|
||||
absl::AnyInvocable<void(FastPairDevice& device)>;
|
||||
// This class detects Fast Pair 'not discoverable' advertisements (see
|
||||
// https://developers.google.com/nearby/fast-pair/spec#AdvertisingWhenNotDiscoverable)
|
||||
// and invokes the |found_callback| when it finds a device within the
|
||||
// appropriate range. |lost_callback| will be invoked when that device is lost.
|
||||
class FastPairNonDiscoverableScanner : public FastPairScanner::Observer {
|
||||
public:
|
||||
class Factory {
|
||||
public:
|
||||
static std::unique_ptr<FastPairNonDiscoverableScanner> Create(
|
||||
FastPairScanner& scanner, NonDiscoverableScannerCallback found_callback,
|
||||
NonDiscoverableScannerCallback lost_callback,
|
||||
SingleThreadExecutor* executor,
|
||||
FastPairDeviceRepository* device_repository);
|
||||
|
||||
static void SetFactoryForTesting(Factory* g_test_factory);
|
||||
|
||||
protected:
|
||||
virtual ~Factory() = default;
|
||||
virtual std::unique_ptr<FastPairNonDiscoverableScanner> CreateInstance(
|
||||
FastPairScanner& scanner, NonDiscoverableScannerCallback found_callback,
|
||||
NonDiscoverableScannerCallback lost_callback,
|
||||
SingleThreadExecutor* executor,
|
||||
FastPairDeviceRepository* device_repository) = 0;
|
||||
|
||||
private:
|
||||
static Factory* g_test_factory_;
|
||||
};
|
||||
|
||||
FastPairNonDiscoverableScanner(FastPairScanner& scanner,
|
||||
NonDiscoverableScannerCallback found_callback,
|
||||
NonDiscoverableScannerCallback lost_callback,
|
||||
SingleThreadExecutor* executor,
|
||||
FastPairDeviceRepository* device_repository);
|
||||
FastPairNonDiscoverableScanner(const FastPairNonDiscoverableScanner&) =
|
||||
delete;
|
||||
FastPairNonDiscoverableScanner& operator=(
|
||||
const FastPairNonDiscoverableScanner&) = delete;
|
||||
~FastPairNonDiscoverableScanner();
|
||||
|
||||
// FastPairScanner::Observer
|
||||
void OnDeviceFound(const BlePeripheral& peripheral) override;
|
||||
void OnDeviceLost(const BlePeripheral& peripheral) override;
|
||||
|
||||
private:
|
||||
void OnAdvertisementParsed(
|
||||
absl::string_view address,
|
||||
std::optional<NonDiscoverableAdvertisement> advertisement);
|
||||
void OnAccountKeyFilterCheckResult(
|
||||
absl::string_view address,
|
||||
std::optional<NonDiscoverableAdvertisement> advertisement,
|
||||
std::optional<AccountKey> account_key,
|
||||
std::optional<absl::string_view> model_id);
|
||||
void OnDeviceMetadataRetrieved(
|
||||
absl::string_view address,
|
||||
std::optional<NonDiscoverableAdvertisement> advertisement,
|
||||
absl::string_view model_id, AccountKey account_key,
|
||||
std::optional<DeviceMetadata> device_metadata);
|
||||
void NotifyDeviceFound(FastPairDevice& device)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_);
|
||||
|
||||
FastPairScanner& scanner_;
|
||||
NonDiscoverableScannerCallback found_callback_ ABSL_GUARDED_BY(*executor_);
|
||||
NonDiscoverableScannerCallback lost_callback_ ABSL_GUARDED_BY(*executor_);
|
||||
SingleThreadExecutor* executor_;
|
||||
FastPairDeviceRepository* device_repository_ ABSL_GUARDED_BY(*executor_);
|
||||
ObserverList<FastPairScanner::Observer> observer_list_;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_NON_DISCOVERABLE_SCANNER_H_
|
||||
@@ -0,0 +1,298 @@
|
||||
// Copyright 2023 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 "fastpair/scanning/fastpair/fast_pair_non_discoverable_scanner.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "fastpair/common/account_key.h"
|
||||
#include "fastpair/repository/fake_fast_pair_repository.h"
|
||||
#include "fastpair/scanning/fastpair/fake_fast_pair_scanner.h"
|
||||
#include "fastpair/testing/fast_pair_service_data_creator.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
namespace {
|
||||
constexpr int kNotDiscoverableAdvHeader = 0b00000110;
|
||||
constexpr int kAccountKeyFilterHeader = 0b01100000;
|
||||
constexpr int kAccountKeyFilterNoNotificationHeader = 0b01100010;
|
||||
constexpr int kSaltHeader = 0b00010001;
|
||||
constexpr absl::string_view kModelId("aabbcc");
|
||||
constexpr absl::string_view kBleAddress("11:12:13:14:15:16");
|
||||
constexpr absl::string_view kAccountKeyFilter("112233445566");
|
||||
constexpr absl::string_view kSalt("01");
|
||||
|
||||
// Short timeout for operation that we expect to timeout.
|
||||
constexpr absl::Duration kFailureTimeout = absl::Milliseconds(100);
|
||||
|
||||
class FakeBlePeripheral : public api::BlePeripheral {
|
||||
public:
|
||||
explicit FakeBlePeripheral(absl::string_view name,
|
||||
std::vector<uint8_t> service_data) {
|
||||
name_ = std::string(name);
|
||||
ByteArray advertisement_bytes(
|
||||
std::string(service_data.begin(), service_data.end()));
|
||||
advertisement_data_ = advertisement_bytes;
|
||||
}
|
||||
|
||||
FakeBlePeripheral(const FakeBlePeripheral&) = default;
|
||||
~FakeBlePeripheral() override = default;
|
||||
|
||||
std::string GetName() const override { return name_; }
|
||||
|
||||
ByteArray GetAdvertisementBytes(
|
||||
const std::string& service_id) const override {
|
||||
return advertisement_data_;
|
||||
}
|
||||
|
||||
void SetName(const std::string& name) { name_ = name; }
|
||||
|
||||
void SetAdvertisementBytes(ByteArray advertisement_bytes) {
|
||||
advertisement_data_ = advertisement_bytes;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
ByteArray advertisement_data_;
|
||||
};
|
||||
|
||||
class FastPairNonDiscoverableScannerTest : public ::testing::Test {
|
||||
protected:
|
||||
void TearDown() override {
|
||||
executor_.Shutdown();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> GetAdvServicedata() {
|
||||
return FastPairServiceDataCreator::Builder()
|
||||
.SetHeader(kNotDiscoverableAdvHeader)
|
||||
.SetModelId(kModelId)
|
||||
.AddExtraFieldHeader(kAccountKeyFilterHeader)
|
||||
.AddExtraField(kAccountKeyFilter)
|
||||
.AddExtraFieldHeader(kSaltHeader)
|
||||
.AddExtraField(kSalt)
|
||||
.Build()
|
||||
->CreateServiceData();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> GetAdvNoUiServicedata() {
|
||||
return FastPairServiceDataCreator::Builder()
|
||||
.SetHeader(kNotDiscoverableAdvHeader)
|
||||
.SetModelId(kModelId)
|
||||
.AddExtraFieldHeader(kAccountKeyFilterNoNotificationHeader)
|
||||
.AddExtraField(kAccountKeyFilter)
|
||||
.AddExtraFieldHeader(kSaltHeader)
|
||||
.AddExtraField(kSalt)
|
||||
.Build()
|
||||
->CreateServiceData();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> GetAdvWrongServicedata() {
|
||||
return FastPairServiceDataCreator::Builder()
|
||||
.SetHeader(kNotDiscoverableAdvHeader)
|
||||
.SetModelId(kModelId)
|
||||
.AddExtraFieldHeader /*InvalidType*/ (0b01100001)
|
||||
.AddExtraField(kAccountKeyFilter)
|
||||
.AddExtraFieldHeader(kSaltHeader)
|
||||
.AddExtraField(kSalt)
|
||||
.Build()
|
||||
->CreateServiceData();
|
||||
}
|
||||
|
||||
SingleThreadExecutor executor_;
|
||||
FastPairDeviceRepository devices_{&executor_};
|
||||
std::unique_ptr<FakeFastPairScanner> scanner_;
|
||||
std::unique_ptr<FastPairNonDiscoverableScanner> non_discoverable_scanner_;
|
||||
};
|
||||
|
||||
TEST_F(FastPairNonDiscoverableScannerTest, FoundAssociatedDevice) {
|
||||
const std::vector<uint8_t> account_key_vec{0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
||||
0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB,
|
||||
0xCC, 0xDD, 0xEE, 0xFF};
|
||||
scanner_ = std::make_unique<FakeFastPairScanner>();
|
||||
auto repository = std::make_unique<FakeFastPairRepository>();
|
||||
proto::Device metadata;
|
||||
repository->SetFakeMetadata(kModelId, metadata);
|
||||
AccountKey account_key(account_key_vec);
|
||||
repository->SetResultOfCheckIfAssociatedWithCurrentAccount(account_key,
|
||||
kModelId);
|
||||
|
||||
auto ble_peripheral =
|
||||
std::make_unique<FakeBlePeripheral>(kBleAddress, GetAdvServicedata());
|
||||
|
||||
absl::Notification found_notification;
|
||||
absl::Notification lost_notification;
|
||||
non_discoverable_scanner_ = FastPairNonDiscoverableScanner::Factory::Create(
|
||||
*scanner_,
|
||||
[&](FastPairDevice& device) {
|
||||
EXPECT_EQ(device.GetModelId(), kModelId);
|
||||
EXPECT_EQ(device.GetBleAddress(), kBleAddress);
|
||||
EXPECT_EQ(device.GetProtocol(), Protocol::kFastPairSubsequentPairing);
|
||||
EXPECT_EQ(device.GetAccountKey(), account_key);
|
||||
EXPECT_TRUE(device.ShouldShowUiNotification());
|
||||
found_notification.Notify();
|
||||
},
|
||||
[&](FastPairDevice& device) { lost_notification.Notify(); }, &executor_,
|
||||
&devices_);
|
||||
|
||||
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
|
||||
found_notification.WaitForNotification();
|
||||
scanner_->NotifyDeviceLost(BlePeripheral(ble_peripheral.get()));
|
||||
lost_notification.WaitForNotification();
|
||||
}
|
||||
|
||||
TEST_F(FastPairNonDiscoverableScannerTest, FoundNonAssociatedDevice) {
|
||||
scanner_ = std::make_unique<FakeFastPairScanner>();
|
||||
auto repository = std::make_unique<FakeFastPairRepository>();
|
||||
proto::Device metadata;
|
||||
repository->SetFakeMetadata(kModelId, metadata);
|
||||
repository->SetResultOfCheckIfAssociatedWithCurrentAccount(std::nullopt,
|
||||
std::nullopt);
|
||||
|
||||
auto ble_peripheral =
|
||||
std::make_unique<FakeBlePeripheral>(kBleAddress, GetAdvServicedata());
|
||||
|
||||
absl::Notification found_notification;
|
||||
absl::Notification lost_notification;
|
||||
non_discoverable_scanner_ = FastPairNonDiscoverableScanner::Factory::Create(
|
||||
*scanner_, [&](FastPairDevice& device) { found_notification.Notify(); },
|
||||
[&](FastPairDevice& device) { lost_notification.Notify(); }, &executor_,
|
||||
&devices_);
|
||||
|
||||
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
|
||||
EXPECT_FALSE(
|
||||
found_notification.WaitForNotificationWithTimeout(kFailureTimeout));
|
||||
scanner_->NotifyDeviceLost(BlePeripheral(ble_peripheral.get()));
|
||||
EXPECT_FALSE(
|
||||
lost_notification.WaitForNotificationWithTimeout(kFailureTimeout));
|
||||
}
|
||||
|
||||
TEST_F(FastPairNonDiscoverableScannerTest, FoundNoUIDevice) {
|
||||
const std::vector<uint8_t> account_key_vec{0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
||||
0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB,
|
||||
0xCC, 0xDD, 0xEE, 0xFF};
|
||||
scanner_ = std::make_unique<FakeFastPairScanner>();
|
||||
auto repository = std::make_unique<FakeFastPairRepository>();
|
||||
proto::Device metadata;
|
||||
repository->SetFakeMetadata(kModelId, metadata);
|
||||
AccountKey account_key(account_key_vec);
|
||||
repository->SetResultOfCheckIfAssociatedWithCurrentAccount(account_key,
|
||||
kModelId);
|
||||
|
||||
auto ble_peripheral =
|
||||
std::make_unique<FakeBlePeripheral>(kBleAddress, GetAdvNoUiServicedata());
|
||||
|
||||
absl::Notification found_notification;
|
||||
absl::Notification lost_notification;
|
||||
non_discoverable_scanner_ = FastPairNonDiscoverableScanner::Factory::Create(
|
||||
*scanner_,
|
||||
[&](FastPairDevice& device) {
|
||||
EXPECT_EQ(device.GetModelId(), kModelId);
|
||||
EXPECT_EQ(device.GetBleAddress(), kBleAddress);
|
||||
EXPECT_EQ(device.GetProtocol(), Protocol::kFastPairSubsequentPairing);
|
||||
EXPECT_EQ(device.GetAccountKey(), account_key);
|
||||
EXPECT_FALSE(device.ShouldShowUiNotification().value());
|
||||
found_notification.Notify();
|
||||
},
|
||||
[&](FastPairDevice& device) { lost_notification.Notify(); }, &executor_,
|
||||
&devices_);
|
||||
|
||||
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
|
||||
found_notification.WaitForNotification();
|
||||
scanner_->NotifyDeviceLost(BlePeripheral(ble_peripheral.get()));
|
||||
lost_notification.WaitForNotification();
|
||||
}
|
||||
|
||||
TEST_F(FastPairNonDiscoverableScannerTest, FailedToGetDeviceMetadata) {
|
||||
scanner_ = std::make_unique<FakeFastPairScanner>();
|
||||
auto repository = std::make_unique<FakeFastPairRepository>();
|
||||
repository->SetResultOfCheckIfAssociatedWithCurrentAccount(AccountKey(),
|
||||
kModelId);
|
||||
|
||||
auto ble_peripheral =
|
||||
std::make_unique<FakeBlePeripheral>(kBleAddress, GetAdvServicedata());
|
||||
|
||||
absl::Notification found_notification;
|
||||
absl::Notification lost_notification;
|
||||
non_discoverable_scanner_ = FastPairNonDiscoverableScanner::Factory::Create(
|
||||
*scanner_, [&](FastPairDevice& device) { found_notification.Notify(); },
|
||||
[&](FastPairDevice& device) { lost_notification.Notify(); }, &executor_,
|
||||
&devices_);
|
||||
|
||||
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
|
||||
EXPECT_FALSE(
|
||||
found_notification.WaitForNotificationWithTimeout(kFailureTimeout));
|
||||
scanner_->NotifyDeviceLost(BlePeripheral(ble_peripheral.get()));
|
||||
EXPECT_FALSE(
|
||||
lost_notification.WaitForNotificationWithTimeout(kFailureTimeout));
|
||||
}
|
||||
|
||||
TEST_F(FastPairNonDiscoverableScannerTest, NoServiceData) {
|
||||
scanner_ = std::make_unique<FakeFastPairScanner>();
|
||||
auto repository = std::make_unique<FakeFastPairRepository>();
|
||||
proto::Device metadata;
|
||||
repository->SetFakeMetadata(kModelId, metadata);
|
||||
repository->SetResultOfCheckIfAssociatedWithCurrentAccount(AccountKey(),
|
||||
kModelId);
|
||||
|
||||
auto ble_peripheral =
|
||||
std::make_unique<FakeBlePeripheral>(kBleAddress, std::vector<uint8_t>());
|
||||
|
||||
absl::Notification found_notification;
|
||||
absl::Notification lost_notification;
|
||||
non_discoverable_scanner_ = FastPairNonDiscoverableScanner::Factory::Create(
|
||||
*scanner_, [&](FastPairDevice& device) { found_notification.Notify(); },
|
||||
[&](FastPairDevice& device) { lost_notification.Notify(); }, &executor_,
|
||||
&devices_);
|
||||
|
||||
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
|
||||
EXPECT_FALSE(
|
||||
found_notification.WaitForNotificationWithTimeout(kFailureTimeout));
|
||||
scanner_->NotifyDeviceLost(BlePeripheral(ble_peripheral.get()));
|
||||
EXPECT_FALSE(
|
||||
lost_notification.WaitForNotificationWithTimeout(kFailureTimeout));
|
||||
}
|
||||
|
||||
TEST_F(FastPairNonDiscoverableScannerTest, FailedToParseNonDiscoverableAdv) {
|
||||
scanner_ = std::make_unique<FakeFastPairScanner>();
|
||||
auto repository = std::make_unique<FakeFastPairRepository>();
|
||||
proto::Device metadata;
|
||||
repository->SetFakeMetadata(kModelId, metadata);
|
||||
repository->SetResultOfCheckIfAssociatedWithCurrentAccount(AccountKey(),
|
||||
kModelId);
|
||||
|
||||
auto ble_peripheral = std::make_unique<FakeBlePeripheral>(
|
||||
kBleAddress, GetAdvWrongServicedata());
|
||||
|
||||
absl::Notification found_notification;
|
||||
absl::Notification lost_notification;
|
||||
non_discoverable_scanner_ = FastPairNonDiscoverableScanner::Factory::Create(
|
||||
*scanner_, [&](FastPairDevice& device) { found_notification.Notify(); },
|
||||
[&](FastPairDevice& device) { lost_notification.Notify(); }, &executor_,
|
||||
&devices_);
|
||||
|
||||
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
|
||||
EXPECT_FALSE(
|
||||
found_notification.WaitForNotificationWithTimeout(kFailureTimeout));
|
||||
scanner_->NotifyDeviceLost(BlePeripheral(ble_peripheral.get()));
|
||||
EXPECT_FALSE(
|
||||
lost_notification.WaitForNotificationWithTimeout(kFailureTimeout));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "absl/functional/bind_front.h"
|
||||
#include "fastpair/common/fast_pair_device.h"
|
||||
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner_impl.h"
|
||||
#include "fastpair/scanning/fastpair/fast_pair_non_discoverable_scanner.h"
|
||||
#include "fastpair/scanning/fastpair/fast_pair_scanner_impl.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
@@ -59,6 +60,7 @@ void ScannerBrokerImpl::RemoveObserver(Observer* observer) {
|
||||
std::unique_ptr<ScannerBroker::ScanningSession>
|
||||
ScannerBrokerImpl::StartScanning(Protocol protocol) {
|
||||
DCHECK(!fast_pair_discoverable_scanner_);
|
||||
DCHECK(!fast_pair_non_discoverable_scanner_);
|
||||
NEARBY_LOGS(VERBOSE) << "Starting Fast Pair Scanning.";
|
||||
scanner_ = std::make_unique<FastPairScannerImpl>(mediums_, executor_);
|
||||
fast_pair_discoverable_scanner_ =
|
||||
@@ -67,6 +69,13 @@ ScannerBrokerImpl::StartScanning(Protocol protocol) {
|
||||
absl::bind_front(&ScannerBrokerImpl::NotifyDeviceFound, this),
|
||||
absl::bind_front(&ScannerBrokerImpl::NotifyDeviceLost, this),
|
||||
executor_, device_repository_);
|
||||
|
||||
fast_pair_non_discoverable_scanner_ =
|
||||
FastPairNonDiscoverableScanner::Factory::Create(
|
||||
*scanner_,
|
||||
absl::bind_front(&ScannerBrokerImpl::NotifyDeviceFound, this),
|
||||
absl::bind_front(&ScannerBrokerImpl::NotifyDeviceLost, this),
|
||||
executor_, device_repository_);
|
||||
scanning_session_ = scanner_->StartScanning();
|
||||
return std::make_unique<ScanningSessionImpl>(this, protocol);
|
||||
}
|
||||
@@ -77,6 +86,7 @@ void ScannerBrokerImpl::StopScanning(Protocol protocol) {
|
||||
observers_.Clear();
|
||||
|
||||
DestroyOnExecutor(std::move(fast_pair_discoverable_scanner_), executor_);
|
||||
DestroyOnExecutor(std::move(fast_pair_non_discoverable_scanner_), executor_);
|
||||
DestroyOnExecutor(std::move(scanner_), executor_);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "fastpair/internal/mediums/mediums.h"
|
||||
#include "fastpair/repository/fast_pair_device_repository.h"
|
||||
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner.h"
|
||||
#include "fastpair/scanning/fastpair/fast_pair_non_discoverable_scanner.h"
|
||||
#include "fastpair/scanning/fastpair/fast_pair_scanner.h"
|
||||
#include "fastpair/scanning/scanner_broker.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
@@ -49,6 +50,8 @@ class ScannerBrokerImpl : public ScannerBroker {
|
||||
SingleThreadExecutor* executor_;
|
||||
std::unique_ptr<FastPairScanner> scanner_;
|
||||
std::unique_ptr<FastPairDiscoverableScanner> fast_pair_discoverable_scanner_;
|
||||
std::unique_ptr<FastPairNonDiscoverableScanner>
|
||||
fast_pair_non_discoverable_scanner_;
|
||||
ObserverList<Observer> observers_;
|
||||
FastPairDeviceRepository* device_repository_;
|
||||
std::unique_ptr<FastPairScanner::ScanningSession> scanning_session_;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
@@ -24,8 +25,9 @@
|
||||
#include "fastpair/common/protocol.h"
|
||||
#include "fastpair/internal/mediums/mediums.h"
|
||||
#include "fastpair/proto/fastpair_rpcs.proto.h"
|
||||
#include "fastpair/scanning/scanner_broker.h"
|
||||
#include "fastpair/repository/fake_fast_pair_repository.h"
|
||||
#include "fastpair/scanning/scanner_broker.h"
|
||||
#include "fastpair/testing/fast_pair_service_data_creator.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
@@ -33,8 +35,12 @@
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
namespace {
|
||||
|
||||
constexpr absl::Duration kTaskWaitTimeout = absl::Milliseconds(1000);
|
||||
constexpr int kNotDiscoverableAdvHeader = 0b00000110;
|
||||
constexpr int kAccountKeyFilterHeader = 0b01100000;
|
||||
constexpr int kSaltHeader = 0b00010001;
|
||||
constexpr absl::string_view kAccountKeyFilter("112233445566");
|
||||
constexpr absl::string_view kSalt("01");
|
||||
constexpr absl::string_view kServiceID{"Fast Pair"};
|
||||
constexpr absl::string_view kModelId{"718c17"};
|
||||
constexpr absl::string_view kFastPairServiceUuid{
|
||||
@@ -69,7 +75,7 @@ class ScannerBrokerImplTest : public testing::Test {
|
||||
MediumEnvironment& env_{MediumEnvironment::Instance()};
|
||||
};
|
||||
|
||||
TEST_F(ScannerBrokerImplTest, CanStartScanning) {
|
||||
TEST_F(ScannerBrokerImplTest, FoundDiscoverableAdvertisement) {
|
||||
env_.Start();
|
||||
// Setup FakeFastPairRepository
|
||||
std::string decoded_key;
|
||||
@@ -113,6 +119,60 @@ TEST_F(ScannerBrokerImplTest, CanStartScanning) {
|
||||
scanning_session.reset();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(ScannerBrokerImplTest, FoundNonDiscoverableAdvertisement) {
|
||||
env_.Start();
|
||||
SingleThreadExecutor executor;
|
||||
FastPairDeviceRepository devices(&executor);
|
||||
auto repository = std::make_unique<FakeFastPairRepository>();
|
||||
proto::Device metadata;
|
||||
repository->SetFakeMetadata(kModelId, metadata);
|
||||
repository->SetResultOfCheckIfAssociatedWithCurrentAccount(AccountKey(),
|
||||
kModelId);
|
||||
|
||||
// Create Fast Pair Scanner and add its observer
|
||||
Mediums mediums_1;
|
||||
auto scanner_broker =
|
||||
std::make_unique<ScannerBrokerImpl>(mediums_1, &executor, &devices);
|
||||
CountDownLatch accept_latch(1);
|
||||
CountDownLatch lost_latch(1);
|
||||
ScannerBrokerObserver observer(scanner_broker.get(), &accept_latch,
|
||||
&lost_latch);
|
||||
|
||||
// Create Advertiser and startAdvertising
|
||||
Mediums mediums_2;
|
||||
std::string service_id(kServiceID);
|
||||
std::vector<uint8_t> service_data =
|
||||
FastPairServiceDataCreator::Builder()
|
||||
.SetHeader(kNotDiscoverableAdvHeader)
|
||||
.SetModelId(kModelId)
|
||||
.AddExtraFieldHeader(kAccountKeyFilterHeader)
|
||||
.AddExtraField(kAccountKeyFilter)
|
||||
.AddExtraFieldHeader(kSaltHeader)
|
||||
.AddExtraField(kSalt)
|
||||
.Build()
|
||||
->CreateServiceData();
|
||||
ByteArray advertisement_bytes(
|
||||
std::string(service_data.begin(), service_data.end()));
|
||||
std::string fast_pair_service_uuid(kFastPairServiceUuid);
|
||||
mediums_2.GetBle().GetMedium().StartAdvertising(
|
||||
service_id, advertisement_bytes, fast_pair_service_uuid);
|
||||
|
||||
// Fast Pair scanner startScanning
|
||||
auto scanning_session =
|
||||
scanner_broker->StartScanning(Protocol::kFastPairInitialPairing);
|
||||
|
||||
// Notify device found
|
||||
EXPECT_TRUE(accept_latch.Await(kTaskWaitTimeout).result());
|
||||
|
||||
// Advertiser stopAdvertising
|
||||
mediums_2.GetBle().GetMedium().StopAdvertising(service_id);
|
||||
|
||||
// Notify device lost
|
||||
EXPECT_TRUE(lost_latch.Await(kTaskWaitTimeout).result());
|
||||
scanning_session.reset();
|
||||
env_.Stop();
|
||||
}
|
||||
} // namespace
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
Reference in New Issue
Block a user