Implement Fast Pair discoverable scanner

PiperOrigin-RevId: 508484936
This commit is contained in:
Qin Wang
2023-02-09 15:01:54 -08:00
committed by Copybara-Service
parent 75feca580b
commit 5cb25a1a70
5 changed files with 687 additions and 0 deletions
+27
View File
@@ -17,9 +17,12 @@ licenses(["notice"])
cc_library(
name = "scanning",
srcs = [
"fast_pair_discoverable_scanner_impl.cc",
"fast_pair_scanner_impl.cc",
],
hdrs = [
"fast_pair_discoverable_scanner.h",
"fast_pair_discoverable_scanner_impl.h",
"fast_pair_scanner.h",
"fast_pair_scanner_impl.h",
],
@@ -31,6 +34,9 @@ cc_library(
"//fastpair/common",
"//fastpair/dataparser",
"//fastpair/internal/ble",
"//fastpair/proto:fastpair_cc_proto",
"//fastpair/repository",
"//fastpair/server_access",
"//internal/base",
"//internal/platform:base",
"//internal/platform:comm",
@@ -63,3 +69,24 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "fast_pair_discoverable_scanner_impl_test",
size = "small",
srcs = [
"fast_pair_discoverable_scanner_impl_test.cc",
],
shard_count = 16,
deps = [
":scanning",
"//fastpair/dataparser",
"//fastpair/server_access:test_support",
"//fastpair/testing",
"//internal/platform:comm",
"//internal/platform:test_util",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/synchronization",
"@com_google_googletest//:gtest_main",
],
)
@@ -0,0 +1,39 @@
// 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_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_DISCOVERABLE_SCANNER_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_DISCOVERABLE_SCANNER_H_
#include "absl/functional/any_invocable.h"
#include "fastpair/common/fast_pair_device.h"
namespace nearby {
namespace fastpair {
using DeviceCallback = absl::AnyInvocable<void(FastPairDevice& device)>;
// This class detects Fast Pair 'discoverable' advertisements (see
// https://developers.google.com/nearby/fast-pair/spec#AdvertisingWhenDiscoverable)
// and invokes the |found_callback| when it finds a device within the
// appropriate range. |lost_callback| will be invoked when that device is lost
// to the bluetooth adapter.
class FastPairDiscoverableScanner {
public:
virtual ~FastPairDiscoverableScanner() = default;
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_DISCOVERABLE_SCANNER_H_
@@ -0,0 +1,213 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner_impl.h"
#include <algorithm>
#include <cstdint>
#include <iterator>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/functional/bind_front.h"
#include "absl/strings/string_view.h"
#include "fastpair/common/constant.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/protocol.h"
#include "fastpair/dataparser/fast_pair_data_parser.h"
#include "fastpair/proto/fastpair_rpcs.pb.h"
#include "fastpair/server_access/fast_pair_repository.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace fastpair {
namespace {
constexpr char kNearbyShareModelId[] = "fc128e";
bool IsValidDeviceType(const proto::Device& device) {
return device.device_type() == proto::DeviceType::HEADPHONES ||
device.device_type() == proto::DeviceType::SPEAKER ||
device.device_type() == proto::DeviceType::TRUE_WIRELESS_HEADPHONES ||
device.device_type() == proto::DeviceType::DEVICE_TYPE_UNSPECIFIED;
}
bool IsSupportedNotificationType(const proto::Device& device) {
// We only allow-list notification types that should trigger a pairing
// notification, since we currently only support pairing. We include
// NOTIFICATION_TYPE_UNSPECIFIED to handle the case where a Provider is
// advertising incorrectly and conservatively allow it to show a notification,
// matching Android behavior.
return device.notification_type() ==
proto::NotificationType::NOTIFICATION_TYPE_UNSPECIFIED ||
device.notification_type() == proto::NotificationType::FAST_PAIR ||
device.notification_type() == proto::NotificationType::FAST_PAIR_ONE;
}
} // namespace
// FastPairScannerImpl::Factory
FastPairDiscoverableScannerImpl::Factory*
FastPairDiscoverableScannerImpl::Factory::g_test_factory_ = nullptr;
std::unique_ptr<FastPairDiscoverableScanner>
FastPairDiscoverableScannerImpl::Factory::Create(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter, DeviceCallback found_callback,
DeviceCallback lost_callback) {
if (g_test_factory_) {
return g_test_factory_->CreateInstance(
std::move(scanner), std::move(adapter), std::move(found_callback),
std::move(lost_callback));
}
return std::make_unique<FastPairDiscoverableScannerImpl>(
std::move(scanner), std::move(adapter), std::move(found_callback),
std::move(lost_callback));
}
void FastPairDiscoverableScannerImpl::Factory::SetFactoryForTesting(
Factory* g_test_factory) {
g_test_factory_ = g_test_factory;
}
FastPairDiscoverableScannerImpl::Factory::~Factory() = default;
// FastPairScannerImpl
FastPairDiscoverableScannerImpl::FastPairDiscoverableScannerImpl(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter, DeviceCallback found_callback,
DeviceCallback lost_callback)
: scanner_(std::move(scanner)),
adapter_(std::move(adapter)),
found_callback_(std::move(found_callback)),
lost_callback_(std::move(lost_callback)) {
scanner_->AddObserver(this);
}
void FastPairDiscoverableScannerImpl::OnDeviceFound(
const BlePeripheral& peripheral) {
ByteArray fast_pair_service_data =
peripheral.GetAdvertisementBytes(kServiceId);
if (fast_pair_service_data.Empty()) {
NEARBY_LOGS(WARNING) << __func__
<< ": Device doesn't have any Fast Pair Service Data.";
return;
}
model_id_parse_attempts_[peripheral.GetName()] = 1;
NEARBY_LOGS(WARNING) << __func__ << ": Attempting to get model ID";
std::vector<uint8_t> service_data;
std::string model_id_bytes = fast_pair_service_data.data();
std::move(std::begin(model_id_bytes), std::end(model_id_bytes),
std::back_inserter(service_data));
FastPairDataParser::GetHexModelIdFromServiceData(
service_data,
{[this, peripheral](absl::optional<absl::string_view> model_id) {
OnModelIdRetrieved(peripheral.GetName(), model_id);
}});
}
void FastPairDiscoverableScannerImpl::OnModelIdRetrieved(
const std::string& address,
const absl::optional<absl::string_view> model_id) {
auto it = model_id_parse_attempts_.find(address);
// If there's no entry in the map, the device was lost while parsing.
if (it == model_id_parse_attempts_.end()) {
NEARBY_LOGS(WARNING)
<< __func__
<< ": Returning early because device as lost while parsing.";
return;
}
model_id_parse_attempts_.erase(it);
if (!model_id.has_value()) {
NEARBY_LOGS(INFO) << __func__
<< ": Returning early because no model id was parsed.";
return;
}
// The Nearby Share feature advertises under the Fast Pair Service Data UUID
// and uses a reserved model ID to enable their 'fast initiation' scenario.
// We must detect this instance and ignore these advertisements since they
// do not correspond to Fast Pair devices that are open to pairing.
if (model_id.value().compare(kNearbyShareModelId) == 0) {
NEARBY_LOGS(WARNING) << __func__ << ": Ignore Nearby Share Model ID.";
return;
}
FastPairRepository::Get()->GetDeviceMetadata(
model_id.value(),
absl::bind_front(
&FastPairDiscoverableScannerImpl::OnDeviceMetadataRetrieved, this,
address, std::string(model_id.value())));
}
void FastPairDiscoverableScannerImpl::OnDeviceMetadataRetrieved(
const std::string& address, const std::string model_id,
DeviceMetadata& device_metadata) {
// Ignore advertisements that aren't for Fast Pair but leverage the service
// UUID.
if (!IsValidDeviceType(device_metadata.GetDetails())) {
NEARBY_LOGS(WARNING)
<< __func__
<< ": Invalid device type for Fast Pair. Ignoring this advertisement";
return;
}
// Ignore advertisements for unsupported notification types, such as
// APP_LAUNCH which should launch a companion app instead of beginning Fast
// Pair.
if (!IsSupportedNotificationType(device_metadata.GetDetails())) {
NEARBY_LOGS(WARNING) << __func__
<< ": Unsupported notification type for Fast Pair. "
"Ignoring this advertisement";
return;
}
FastPairDevice device(model_id, address, Protocol::kFastPairInitialPairing);
NotifyDeviceFound(device);
}
void FastPairDiscoverableScannerImpl::NotifyDeviceFound(
FastPairDevice& device) {
NEARBY_LOGS(VERBOSE) << "Notify Device found:"
<< "BluetoothAddress = " << device.ble_address
<< ", Model id = " << device.model_id;
notified_devices_[device.ble_address] = &device;
found_callback_(device);
}
void FastPairDiscoverableScannerImpl::OnDeviceLost(
const BlePeripheral& peripheral) {
NEARBY_LOGS(INFO) << __func__ << ": Running lost callback";
model_id_parse_attempts_.erase(peripheral.GetName());
auto it = notified_devices_.find(peripheral.GetName());
// Don't invoke callback if we didn't notify this device.
if (it == notified_devices_.end()) return;
FastPairDevice* notified_device = it->second;
notified_devices_.erase(it);
lost_callback_(*notified_device);
}
} // namespace fastpair
} // namespace nearby
@@ -0,0 +1,90 @@
// 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_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_DISCOVERABLE_SCANNER_IMPL_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_DISCOVERABLE_SCANNER_IMPL_H_
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/repository/device_metadata.h"
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner.h"
#include "internal/base/observer_list.h"
#include "internal/platform/bluetooth_adapter.h"
namespace nearby {
namespace fastpair {
class FastPairDiscoverableScannerImpl : public FastPairDiscoverableScanner,
public FastPairScanner::Observer {
public:
class Factory {
public:
static std::unique_ptr<FastPairDiscoverableScanner> Create(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter,
DeviceCallback found_callback, DeviceCallback lost_callback);
static void SetFactoryForTesting(Factory* g_test_factory);
protected:
virtual ~Factory();
virtual std::unique_ptr<FastPairDiscoverableScanner> CreateInstance(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter,
DeviceCallback found_callback, DeviceCallback lost_callback) = 0;
private:
static Factory* g_test_factory_;
};
FastPairDiscoverableScannerImpl(std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter,
DeviceCallback found_callback,
DeviceCallback lost_callback);
FastPairDiscoverableScannerImpl(const FastPairDiscoverableScannerImpl&) =
delete;
FastPairDiscoverableScannerImpl& operator=(
const FastPairDiscoverableScannerImpl&) = delete;
~FastPairDiscoverableScannerImpl() override = default;
// FastPairScanner::Observer
void OnDeviceFound(const BlePeripheral& peripheral) override;
void OnDeviceLost(const BlePeripheral& peripheral) override;
private:
void OnModelIdRetrieved(const std::string& address,
std::optional<absl::string_view> model_id);
void OnDeviceMetadataRetrieved(const std::string& address,
const std::string model_id,
DeviceMetadata& device_metadata);
void NotifyDeviceFound(FastPairDevice& device);
std::shared_ptr<FastPairScanner> scanner_;
std::shared_ptr<BluetoothAdapter> adapter_;
DeviceCallback found_callback_;
DeviceCallback lost_callback_;
absl::flat_hash_map<std::string, FastPairDevice*> notified_devices_;
absl::flat_hash_map<std::string, int> model_id_parse_attempts_;
ObserverList<FastPairScanner::Observer> observer_list_;
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_DISCOVERABLE_SCANNER_IMPL_H_
@@ -0,0 +1,318 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner_impl.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/synchronization/notification.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner_impl.h"
#include "fastpair/server_access/fake_fast_pair_repository.h"
#include "fastpair/testing/fast_pair_service_data_creator.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/medium_environment.h"
namespace nearby {
namespace fastpair {
namespace {
constexpr absl::Duration kWaitTimeout = absl::Milliseconds(200);
constexpr char kValidModelId[] = "718c17";
constexpr char kInvalidModelId[] = "12345";
constexpr char kNearbyShareModelId[] = "fc128e";
constexpr char kTestBleDeviceAddress[] = "11:12:13:14:15:16";
class FakeBlePeripheral : public api::BlePeripheral {
public:
explicit FakeBlePeripheral(absl::string_view name,
absl::string_view model_id) {
name_ = std::string(name);
const std::vector<uint8_t> service_data =
FastPairServiceDataCreator::Builder()
.SetModelId(std::string(model_id))
.Build()
->CreateServiceData();
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 FastPairDiscoverableScannerImplTest : public testing::Test {
public:
void SetUp() override {
SetUpMetadata();
scanner_ = std::make_shared<FastPairScannerImpl>();
adapter_ = std::make_shared<BluetoothAdapter>();
}
void SetUpMetadata() {
repository_ = std::make_unique<FakeFastPairRepository>();
proto::Device metadata;
metadata.set_device_type(proto::DeviceType::TRUE_WIRELESS_HEADPHONES);
repository_->SetFakeMetadata(kValidModelId, metadata);
}
// void TearDown() override { discoverable_scanner_.reset(); }
protected:
std::shared_ptr<FastPairScannerImpl> scanner_;
std::unique_ptr<FakeFastPairRepository> repository_;
std::shared_ptr<BluetoothAdapter> adapter_;
DeviceCallback found_device_callback_;
DeviceCallback lost_device_callback_;
};
TEST_F(FastPairDiscoverableScannerImplTest, ValidModelId) {
absl::Notification found_notification;
absl::Notification lost_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
lost_device_callback_ = [&lost_notification](FastPairDevice& device) {
lost_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
std::make_unique<FakeBlePeripheral>(kTestBleDeviceAddress, kValidModelId);
scanner_->OnDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_TRUE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
scanner_->OnDeviceLost(BlePeripheral(ble_peripheral.get()));
EXPECT_TRUE(lost_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest, InvalidModelId) {
absl::Notification found_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral = std::make_unique<FakeBlePeripheral>(
kTestBleDeviceAddress, kInvalidModelId);
scanner_->OnDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_FALSE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest, NoServiceData) {
absl::Notification found_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
std::make_unique<FakeBlePeripheral>(kTestBleDeviceAddress, "");
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_FALSE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest, UnsupportedDeviceType) {
proto::Device metadata;
metadata.set_device_type(proto::DeviceType::AUTOMOTIVE);
repository_->SetFakeMetadata(kValidModelId, metadata);
absl::Notification found_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
std::make_unique<FakeBlePeripheral>(kTestBleDeviceAddress, kValidModelId);
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_FALSE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest, UnsupportedNotifictionType) {
proto::Device metadata;
metadata.set_device_type(proto::DeviceType::HEADPHONES);
metadata.set_notification_type(proto::NotificationType::APP_LAUNCH);
repository_->SetFakeMetadata(kValidModelId, metadata);
absl::Notification found_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
std::make_unique<FakeBlePeripheral>(kTestBleDeviceAddress, kValidModelId);
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_FALSE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest, UnspecifiedNotificationType) {
// Set metadata to mimic a device that doesn't specify the notification
// or device type. Since we aren't sure what this device is, we'll show
// the notification to be safe.
proto::Device metadata;
metadata.set_device_type(proto::DeviceType::DEVICE_TYPE_UNSPECIFIED);
metadata.set_notification_type(
proto::NotificationType::NOTIFICATION_TYPE_UNSPECIFIED);
repository_->SetFakeMetadata(kValidModelId, metadata);
absl::Notification found_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
std::make_unique<FakeBlePeripheral>(kTestBleDeviceAddress, kValidModelId);
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_TRUE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest, V1NotificationType) {
// Set metadata to mimic a V1 device which advertises with no device
// type and a notification type of FAST_PAIR_ONE.
proto::Device metadata;
metadata.set_device_type(proto::DeviceType::DEVICE_TYPE_UNSPECIFIED);
metadata.set_notification_type(proto::NotificationType::FAST_PAIR_ONE);
repository_->SetFakeMetadata(kValidModelId, metadata);
absl::Notification found_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
std::make_unique<FakeBlePeripheral>(kTestBleDeviceAddress, kValidModelId);
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_TRUE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest, V2NotificationType) {
// Set metadata to mimic a V2 device which advertises with a device
// type of TRUE_WIRELESS_HEADPHONES and a notification type of FAST_PAIR.
proto::Device metadata;
metadata.set_device_type(proto::DeviceType::TRUE_WIRELESS_HEADPHONES);
metadata.set_notification_type(proto::NotificationType::FAST_PAIR);
repository_->SetFakeMetadata(kValidModelId, metadata);
absl::Notification found_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
std::make_unique<FakeBlePeripheral>(kTestBleDeviceAddress, kValidModelId);
scanner_->NotifyDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_TRUE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest, NearbyShareModelId) {
absl::Notification found_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral = std::make_unique<FakeBlePeripheral>(
kTestBleDeviceAddress, kNearbyShareModelId);
scanner_->OnDeviceFound(BlePeripheral(ble_peripheral.get()));
EXPECT_FALSE(found_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
TEST_F(FastPairDiscoverableScannerImplTest,
DoesntInvokeLostCallbackIfDidntInvokeFound) {
absl::Notification found_notification;
absl::Notification lost_notification;
found_device_callback_ = [&found_notification](FastPairDevice& device) {
found_notification.Notify();
};
lost_device_callback_ = [&lost_notification](FastPairDevice& device) {
lost_notification.Notify();
};
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
std::make_unique<FakeBlePeripheral>(kTestBleDeviceAddress, kValidModelId);
scanner_->OnDeviceLost(BlePeripheral(ble_peripheral.get()));
EXPECT_FALSE(lost_notification.WaitForNotificationWithTimeout(kWaitTimeout));
}
} // namespace
} // namespace fastpair
} // namespace nearby