mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Add retro pairing in scalable seeker
Listen for manual pairing events and notify plugins. Add retroactive pairing flow in the scalable seeker. Actually upload the account key to the provider. Missing bits: - Notify the user and get their permission, - Upload the new Account Key to user's account. PiperOrigin-RevId: 544616348
This commit is contained in:
committed by
Copybara-Service
parent
a8b6fdee59
commit
e00bdfb3e3
@@ -34,6 +34,7 @@ cc_library(
|
||||
"//internal/platform:types",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "fastpair/common/protocol.h"
|
||||
#include "fastpair/handshake/fast_pair_data_encryptor_impl.h"
|
||||
#include "fastpair/message_stream/message_stream.h"
|
||||
@@ -32,18 +33,13 @@
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
FastPairController::FastPairController(Mediums* mediums,
|
||||
const BluetoothDevice& device,
|
||||
FastPairController::FastPairController(Mediums* mediums, FastPairDevice* device,
|
||||
SingleThreadExecutor* executor)
|
||||
: mediums_(mediums),
|
||||
device_(Protocol::kFastPairRetroactivePairing),
|
||||
executor_(executor) {
|
||||
device_.SetPublicAddress(device.GetMacAddress());
|
||||
}
|
||||
: mediums_(mediums), device_(device), executor_(executor) {}
|
||||
|
||||
absl::Status FastPairController::OpenMessageStream() {
|
||||
message_stream_ = std::make_unique<MessageStream>(
|
||||
device_, &mediums_->GetBluetoothClassic().GetMedium(), *this);
|
||||
*device_, &mediums_->GetBluetoothClassic().GetMedium(), *this);
|
||||
return message_stream_->OpenRfcomm();
|
||||
}
|
||||
|
||||
@@ -51,10 +47,10 @@ void FastPairController::AddMessageStreamConnectionObserver(
|
||||
MessageStreamConnectionObserver* observer) {
|
||||
connection_observers_.AddObserver(observer);
|
||||
if (message_stream_status_.ok() && observer->on_connected != nullptr) {
|
||||
observer->on_connected(device_);
|
||||
observer->on_connected(*device_);
|
||||
} else if (!message_stream_status_.ok() &&
|
||||
observer->on_disconnected != nullptr) {
|
||||
observer->on_disconnected(device_, message_stream_status_);
|
||||
observer->on_disconnected(*device_, message_stream_status_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,8 +62,8 @@ void FastPairController::RemoveMessageStreamConnectionObserver(
|
||||
void FastPairController::AddAddressRotationObserver(
|
||||
BleAddressRotationObserver* observer) {
|
||||
address_rotation_observers_.AddObserver(observer);
|
||||
if (!device_.GetBleAddress().empty()) {
|
||||
observer->on_ble_address_rotated(device_, device_.GetBleAddress());
|
||||
if (!device_->GetBleAddress().empty()) {
|
||||
observer->on_ble_address_rotated(*device_, device_->GetBleAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,8 +74,8 @@ void FastPairController::RemoveAddressRotationObserver(
|
||||
|
||||
void FastPairController::AddModelIdObserver(ModelIdObserver* observer) {
|
||||
model_id_observers_.AddObserver(observer);
|
||||
if (!device_.GetModelId().empty()) {
|
||||
observer->on_model_id(device_);
|
||||
if (!device_->GetModelId().empty()) {
|
||||
observer->on_model_id(*device_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,12 +88,12 @@ FastPairController::GetDataEncryptor() {
|
||||
if (!encryptor_) {
|
||||
encryptor_ =
|
||||
std::make_unique<Future<std::shared_ptr<FastPairDataEncryptor>>>();
|
||||
if (device_.GetMetadata()) {
|
||||
if (device_->GetMetadata()) {
|
||||
CreateDataEncryptor();
|
||||
} else {
|
||||
FastPairRepository::Get()->GetDeviceMetadata(
|
||||
device_.GetModelId(), [this](DeviceMetadata& metadata) {
|
||||
device_.SetMetadata(metadata);
|
||||
device_->GetModelId(), [this](DeviceMetadata& metadata) {
|
||||
device_->SetMetadata(metadata);
|
||||
CreateDataEncryptor();
|
||||
});
|
||||
}
|
||||
@@ -107,8 +103,8 @@ FastPairController::GetDataEncryptor() {
|
||||
|
||||
void FastPairController::CreateDataEncryptor() {
|
||||
FastPairDataEncryptorImpl::Factory::CreateAsync(
|
||||
device_, [borrowable = lender_.GetBorrowable()](
|
||||
std::unique_ptr<FastPairDataEncryptor> encryptor) mutable {
|
||||
*device_, [borrowable = lender_.GetBorrowable()](
|
||||
std::unique_ptr<FastPairDataEncryptor> encryptor) mutable {
|
||||
auto borrowed = borrowable.Borrow();
|
||||
if (borrowed) {
|
||||
(*borrowed)->SetDataEncryptor(std::move(encryptor));
|
||||
@@ -122,7 +118,7 @@ FastPairController::GetGattClientRef() {
|
||||
if (gatt_client_ == nullptr) {
|
||||
gatt_client_ref_count_ = 0;
|
||||
gatt_client_ = FastPairGattServiceClientImpl::Factory::Create(
|
||||
device_, *mediums_, executor_);
|
||||
*device_, *mediums_, executor_);
|
||||
gatt_client_->InitializeGattConnection(
|
||||
[](std::optional<PairFailure> result) {
|
||||
if (result.has_value()) {
|
||||
@@ -146,7 +142,7 @@ void FastPairController::OnConnectionResult(absl::Status result) {
|
||||
}
|
||||
for (auto* observer : connection_observers_.GetObservers()) {
|
||||
if (observer->on_connected != nullptr) {
|
||||
observer->on_connected(device_);
|
||||
observer->on_connected(*device_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,24 +151,25 @@ void FastPairController::OnDisconnected(absl::Status status) {
|
||||
message_stream_status_ = status;
|
||||
for (auto* observer : connection_observers_.GetObservers()) {
|
||||
if (observer->on_disconnected != nullptr) {
|
||||
observer->on_disconnected(device_, status);
|
||||
observer->on_disconnected(*device_, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
void FastPairController::OnEnableSilenceMode(bool enable) {}
|
||||
void FastPairController::OnLogBufferFull() {}
|
||||
void FastPairController::OnModelId(absl::string_view model_id) {
|
||||
device_.SetModelId(model_id);
|
||||
device_->SetModelId(absl::BytesToHexString(model_id));
|
||||
NEARBY_LOGS(INFO) << "Setting model id: " << device_->GetModelId();
|
||||
for (auto* observer : model_id_observers_.GetObservers()) {
|
||||
observer->on_model_id(device_);
|
||||
observer->on_model_id(*device_);
|
||||
}
|
||||
}
|
||||
|
||||
void FastPairController::OnBleAddressUpdated(absl::string_view address) {
|
||||
std::string old_address = std::string(device_.GetBleAddress());
|
||||
device_.SetBleAddress(address);
|
||||
std::string old_address = std::string(device_->GetBleAddress());
|
||||
device_->SetBleAddress(address);
|
||||
for (auto* observer : address_rotation_observers_.GetObservers()) {
|
||||
observer->on_ble_address_rotated(device_, old_address);
|
||||
observer->on_ble_address_rotated(*device_, old_address);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ class FastPairController : public MessageStream::Observer {
|
||||
FastPairController* controller_ = nullptr;
|
||||
};
|
||||
// Creates a device controller in retroactive pairing path.
|
||||
FastPairController(Mediums* mediums, const BluetoothDevice& device,
|
||||
FastPairController(Mediums* mediums, FastPairDevice* device,
|
||||
SingleThreadExecutor* executor);
|
||||
|
||||
~FastPairController() override {
|
||||
@@ -155,7 +155,10 @@ class FastPairController : public MessageStream::Observer {
|
||||
void OnRemainingBatteryTime(absl::Duration duration) override;
|
||||
bool OnRing(uint8_t components, absl::Duration duration) override;
|
||||
|
||||
const FastPairDevice& GetDevice() { return device_; }
|
||||
FastPairDevice& GetDevice() { return *device_; }
|
||||
std::string GetSeekerMacAddress() const {
|
||||
return mediums_->GetBluetoothClassic().GetMedium().GetMacAddress();
|
||||
}
|
||||
|
||||
private:
|
||||
void SetDataEncryptor(std::unique_ptr<FastPairDataEncryptor> encryptor) {
|
||||
@@ -177,7 +180,7 @@ class FastPairController : public MessageStream::Observer {
|
||||
}
|
||||
void CreateDataEncryptor();
|
||||
Mediums* mediums_;
|
||||
FastPairDevice device_;
|
||||
FastPairDevice* device_;
|
||||
SingleThreadExecutor* executor_;
|
||||
std::unique_ptr<Future<std::shared_ptr<FastPairDataEncryptor>>> encryptor_;
|
||||
std::unique_ptr<MessageStream> message_stream_;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "fastpair/fast_pair_controller.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
@@ -45,6 +46,9 @@ class FastPairControllerTest : public testing::Test {
|
||||
NEARBY_LOGS(INFO) << "Provider address: " << address;
|
||||
remote_device_ = seeker_medium.GetRemoteDevice(provider_.GetMacAddress());
|
||||
ASSERT_TRUE(remote_device_.IsValid());
|
||||
fast_pair_device_ =
|
||||
std::make_unique<FastPairDevice>(Protocol::kFastPairRetroactivePairing);
|
||||
fast_pair_device_->SetPublicAddress(remote_device_.GetMacAddress());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
@@ -60,14 +64,15 @@ class FastPairControllerTest : public testing::Test {
|
||||
Mediums mediums_;
|
||||
FakeProvider provider_;
|
||||
BluetoothDevice remote_device_;
|
||||
std::unique_ptr<FastPairDevice> fast_pair_device_;
|
||||
};
|
||||
|
||||
TEST_F(FastPairControllerTest, Constructor) {
|
||||
FastPairController controller(&mediums_, remote_device_, &executor_);
|
||||
FastPairController controller(&mediums_, &*fast_pair_device_, &executor_);
|
||||
}
|
||||
|
||||
TEST_F(FastPairControllerTest, OpenMessageStream) {
|
||||
FastPairController controller(&mediums_, remote_device_, &executor_);
|
||||
FastPairController controller(&mediums_, &*fast_pair_device_, &executor_);
|
||||
|
||||
EXPECT_OK(controller.OpenMessageStream());
|
||||
}
|
||||
|
||||
@@ -11,14 +11,15 @@ cc_library(
|
||||
"//fastpair:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//fastpair:fast_pair_controller",
|
||||
"//fastpair:fast_pair_events",
|
||||
"//fastpair:fast_pair_seeker",
|
||||
"//fastpair/internal/mediums",
|
||||
"//fastpair/pairing",
|
||||
"//fastpair/repository:device_repository",
|
||||
"//fastpair/retroactive",
|
||||
"//fastpair/scanning:scanner",
|
||||
"//internal/platform:types",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
],
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "fastpair/fast_pair_controller.h"
|
||||
#include "fastpair/fast_pair_events.h"
|
||||
#include "fastpair/pairing/pairer_broker_impl.h"
|
||||
#include "fastpair/scanning/scanner_broker_impl.h"
|
||||
@@ -36,6 +37,9 @@ FastPairSeekerImpl::FastPairSeekerImpl(ServiceCallbacks callbacks,
|
||||
pairer_broker_ = std::make_unique<PairerBrokerImpl>(mediums_, executor_);
|
||||
pairer_broker_->AddObserver(this);
|
||||
mediums_.GetBluetoothClassic().AddObserver(this);
|
||||
retro_detector_ = std::make_unique<RetroactivePairingDetectorImpl>(
|
||||
mediums_, devices, executor);
|
||||
retro_detector_->AddObserver(this);
|
||||
}
|
||||
|
||||
FastPairSeekerImpl::~FastPairSeekerImpl() {
|
||||
@@ -67,7 +71,23 @@ absl::Status FastPairSeekerImpl::StartSubsequentPairing(
|
||||
absl::Status FastPairSeekerImpl::StartRetroactivePairing(
|
||||
const FastPairDevice& device, const RetroactivePairingParam& param,
|
||||
PairingCallback callback) {
|
||||
return absl::UnimplementedError("StartRetroactivePairing");
|
||||
if (pairer_broker_->IsPairing()) {
|
||||
return absl::AlreadyExistsError("Already pairing");
|
||||
}
|
||||
|
||||
device_under_pairing_ = &const_cast<FastPairDevice&>(device);
|
||||
controller_ = std::make_unique<FastPairController>(
|
||||
&mediums_, device_under_pairing_, executor_);
|
||||
retroactive_pair_ = std::make_unique<Retroactive>(controller_.get());
|
||||
pairing_callback_ = std::make_unique<PairingCallback>(std::move(callback));
|
||||
retroactive_pair_->Pair().AddListener(
|
||||
[this](ExceptionOr<absl::Status> result) {
|
||||
retroactive_pair_.reset();
|
||||
controller_.reset();
|
||||
FinishPairing(result.result());
|
||||
},
|
||||
executor_);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status FastPairSeekerImpl::StartFastPairScan() {
|
||||
@@ -184,30 +204,35 @@ void FastPairSeekerImpl::InvalidateScanningState() {
|
||||
}
|
||||
|
||||
void FastPairSeekerImpl::DeviceAdded(BluetoothDevice& device) {
|
||||
NEARBY_LOGS(VERBOSE) << "__func__(" << device.GetMacAddress() << ")";
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "(" << device.GetMacAddress() << ")";
|
||||
}
|
||||
|
||||
void FastPairSeekerImpl::DeviceRemoved(BluetoothDevice& device) {
|
||||
NEARBY_LOGS(VERBOSE) << "__func__(" << device.GetMacAddress() << ")";
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "(" << device.GetMacAddress() << ")";
|
||||
}
|
||||
|
||||
void FastPairSeekerImpl::DeviceAddressChanged(BluetoothDevice& device,
|
||||
absl::string_view old_address) {
|
||||
NEARBY_LOGS(VERBOSE) << "__func__(" << device.GetMacAddress() << ", "
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "(" << device.GetMacAddress() << ", "
|
||||
<< old_address << ")";
|
||||
}
|
||||
|
||||
void FastPairSeekerImpl::DevicePairedChanged(BluetoothDevice& device,
|
||||
bool new_paired_status) {
|
||||
NEARBY_LOGS(VERBOSE) << "__func__(" << device.GetMacAddress() << ", "
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "(" << device.GetMacAddress() << ", "
|
||||
<< new_paired_status << ")";
|
||||
}
|
||||
|
||||
void FastPairSeekerImpl::DeviceConnectedStateChanged(BluetoothDevice& device,
|
||||
bool connected) {
|
||||
NEARBY_LOGS(VERBOSE) << "__func__(" << device.GetMacAddress() << ", "
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "(" << device.GetMacAddress() << ", "
|
||||
<< connected << ")";
|
||||
}
|
||||
|
||||
void FastPairSeekerImpl::OnRetroactivePairFound(FastPairDevice& device) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": " << device;
|
||||
callbacks_.on_pair_event(device, PairEvent{});
|
||||
}
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -19,11 +19,14 @@
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "fastpair/fast_pair_controller.h"
|
||||
#include "fastpair/fast_pair_events.h"
|
||||
#include "fastpair/fast_pair_seeker.h"
|
||||
#include "fastpair/internal/mediums/mediums.h"
|
||||
#include "fastpair/pairing/pairer_broker_impl.h"
|
||||
#include "fastpair/repository/fast_pair_device_repository.h"
|
||||
#include "fastpair/retroactive/retroactive.h"
|
||||
#include "fastpair/retroactive/retroactive_pairing_detector_impl.h"
|
||||
#include "fastpair/scanning/scanner_broker_impl.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
|
||||
@@ -44,7 +47,8 @@ class FastPairSeekerExt : public FastPairSeeker {
|
||||
class FastPairSeekerImpl : public FastPairSeekerExt,
|
||||
ScannerBrokerImpl::Observer,
|
||||
PairerBroker::Observer,
|
||||
BluetoothClassicMedium::Observer {
|
||||
BluetoothClassicMedium::Observer,
|
||||
RetroactivePairingDetector::Observer {
|
||||
public:
|
||||
struct ServiceCallbacks {
|
||||
absl::AnyInvocable<void(const FastPairDevice&, InitialDiscoveryEvent)>
|
||||
@@ -91,6 +95,9 @@ class FastPairSeekerImpl : public FastPairSeekerExt,
|
||||
void DeviceConnectedStateChanged(BluetoothDevice& device,
|
||||
bool connected) override;
|
||||
|
||||
// From RetroactivePairingDetector::Observer.
|
||||
void OnRetroactivePairFound(FastPairDevice& device) override;
|
||||
|
||||
// Internal methods, not exported to plugins.
|
||||
private:
|
||||
// From ScannerBrokerImpl::Observer.
|
||||
@@ -116,6 +123,9 @@ class FastPairSeekerImpl : public FastPairSeekerExt,
|
||||
std::unique_ptr<ScannerBrokerImpl::ScanningSession> scanning_session_;
|
||||
std::unique_ptr<PairerBrokerImpl> pairer_broker_;
|
||||
std::unique_ptr<PairingCallback> pairing_callback_;
|
||||
std::unique_ptr<RetroactivePairingDetectorImpl> retro_detector_;
|
||||
std::unique_ptr<FastPairController> controller_;
|
||||
std::unique_ptr<Retroactive> retroactive_pair_;
|
||||
FastPairDevice* device_under_pairing_ = nullptr;
|
||||
FastPairDevice* test_device_ = nullptr;
|
||||
bool is_screen_locked_ = false;
|
||||
|
||||
@@ -187,6 +187,40 @@ TEST_F(FastPairSeekerImplTest, InitialPairing) {
|
||||
EXPECT_EQ(provider.GetAccountKey(), fp_device.value()->GetAccountKey());
|
||||
}
|
||||
|
||||
TEST_F(FastPairSeekerImplTest, RetroactivePairing) {
|
||||
NEARBY_LOG_SET_SEVERITY(VERBOSE);
|
||||
FakeProvider provider;
|
||||
CountDownLatch pair_latch(1);
|
||||
CountDownLatch retro_latch(1);
|
||||
fast_pair_seeker_ = std::make_unique<FastPairSeekerImpl>(
|
||||
FastPairSeekerImpl::ServiceCallbacks{
|
||||
.on_pair_event =
|
||||
[&](const FastPairDevice& device, PairEvent event) {
|
||||
NEARBY_LOGS(INFO) << "Pair callback";
|
||||
pair_latch.CountDown();
|
||||
EXPECT_OK(fast_pair_seeker_->StartRetroactivePairing(
|
||||
device, RetroactivePairingParam{},
|
||||
{.on_pairing_result = [&](const FastPairDevice&,
|
||||
absl::Status status) {
|
||||
EXPECT_OK(status);
|
||||
retro_latch.CountDown();
|
||||
}}));
|
||||
}},
|
||||
&executor_, &devices_);
|
||||
|
||||
provider.PrepareForRetroactivePairing(
|
||||
{.private_key = absl::HexStringToBytes(kBobPrivateKey),
|
||||
.public_key = absl::HexStringToBytes(kBobPublicKey),
|
||||
.model_id = std::string(kModelId)},
|
||||
&fake_gatt_callbacks_);
|
||||
|
||||
EXPECT_TRUE(pair_latch.Await().Ok());
|
||||
EXPECT_TRUE(retro_latch.Await().Ok());
|
||||
auto fp_device = devices_.FindDevice(provider.GetMacAddress());
|
||||
ASSERT_TRUE(fp_device.has_value());
|
||||
EXPECT_EQ(provider.GetAccountKey(), fp_device.value()->GetAccountKey());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
#include "fastpair/message_stream/fake_provider.h"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/strings/numbers.h"
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include <openssl/base.h>
|
||||
#include <openssl/bn.h>
|
||||
@@ -321,6 +323,13 @@ void FakeProvider::ConfigurePairingContext(absl::string_view pass_key) {
|
||||
CHECK(absl::SimpleAtoi(pass_key, &pass_key_));
|
||||
}
|
||||
|
||||
void FakeProvider::SetPairedStatus(bool paired) {
|
||||
auto device = MediumEnvironment::Instance().FindBluetoothDevice(
|
||||
provider_medium_.GetMacAddress());
|
||||
CHECK_NE(device, nullptr);
|
||||
MediumEnvironment::Instance().SetPairingState(device, paired);
|
||||
}
|
||||
|
||||
void FakeProvider::PrepareForInitialPairing(
|
||||
PairingConfig config, FakeGattCallbacks *fake_gatt_callbacks) {
|
||||
LoadAntiSpoofingKey(config.private_key, config.public_key);
|
||||
@@ -335,5 +344,47 @@ void FakeProvider::PrepareForInitialPairing(
|
||||
StartDiscoverableAdvertisement(config.model_id);
|
||||
}
|
||||
|
||||
ByteArray FakeProvider::GetModelIdMessage(absl::string_view model_id) {
|
||||
std::string binary_id = absl::HexStringToBytes(model_id);
|
||||
std::array<char, 7> data = {3, 1, 0, 3, binary_id[0], binary_id[1],
|
||||
binary_id[2]};
|
||||
return ByteArray(data);
|
||||
}
|
||||
|
||||
ByteArray FakeProvider::GetBleAddressMessage() {
|
||||
std::string data =
|
||||
absl::HexStringToBytes("03020006") + GetMacAddressAsBytes();
|
||||
return ByteArray(data);
|
||||
}
|
||||
|
||||
void FakeProvider::EnableProviderRfcommForRetro(PairingConfig &config) {
|
||||
std::string service_name{"service"};
|
||||
std::string uuid(kRfcommUuid);
|
||||
provider_server_socket_ =
|
||||
provider_medium_.ListenForService(service_name, uuid);
|
||||
model_id_ = config.model_id;
|
||||
provider_thread_.Execute([this]() {
|
||||
provider_socket_ = provider_server_socket_.Accept();
|
||||
if (provider_server_socket_.IsValid()) {
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< "Message stream connected. Sending Model Id and BLE address";
|
||||
provider_socket_.GetOutputStream().Write(GetModelIdMessage(model_id_));
|
||||
provider_socket_.GetOutputStream().Write(GetBleAddressMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FakeProvider::PrepareForRetroactivePairing(
|
||||
PairingConfig config, FakeGattCallbacks *fake_gatt_callbacks) {
|
||||
LoadAntiSpoofingKey(config.private_key, config.public_key);
|
||||
StartGattServer(fake_gatt_callbacks);
|
||||
InsertCorrectGattCharacteristics();
|
||||
SetKeyBasedPairingCallback();
|
||||
SetAccountkeyCallback();
|
||||
EnableProviderRfcommForRetro(config);
|
||||
provider_adapter_.SetScanMode(BluetoothAdapter::ScanMode::kConnectable);
|
||||
SetPairedStatus(true);
|
||||
}
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -85,6 +85,10 @@ class FakeProvider {
|
||||
void PrepareForInitialPairing(PairingConfig config,
|
||||
FakeGattCallbacks* fake_gatt_callbacks);
|
||||
|
||||
// Sets the fake provider up for retroactive pairing
|
||||
void PrepareForRetroactivePairing(PairingConfig config,
|
||||
FakeGattCallbacks* fake_gatt_callbacks);
|
||||
|
||||
void Shutdown() {
|
||||
StopAdvertising();
|
||||
provider_thread_.Shutdown();
|
||||
@@ -211,6 +215,10 @@ class FakeProvider {
|
||||
void SetKeyBasedPairingCallback();
|
||||
void SetPasskeyCallback();
|
||||
void SetAccountkeyCallback();
|
||||
void SetPairedStatus(bool paired);
|
||||
void EnableProviderRfcommForRetro(PairingConfig& config);
|
||||
ByteArray GetModelIdMessage(absl::string_view model_id);
|
||||
ByteArray GetBleAddressMessage();
|
||||
std::string GenSec256r1Secret(absl::string_view remote_party_public_key);
|
||||
std::string CreateSharedSecret(absl::string_view remote_public_key);
|
||||
BluetoothAdapter provider_adapter_;
|
||||
|
||||
@@ -36,6 +36,7 @@ cc_library(
|
||||
"//fastpair/internal/mediums",
|
||||
"//fastpair/message_stream",
|
||||
"//fastpair/pairing",
|
||||
"//fastpair/repository:device_repository",
|
||||
"//internal/base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:types",
|
||||
@@ -54,6 +55,7 @@ cc_test(
|
||||
],
|
||||
deps = [
|
||||
":retroactive",
|
||||
"//fastpair/common",
|
||||
"//fastpair/message_stream:fake_gatt_callbacks",
|
||||
"//fastpair/message_stream:fake_provider",
|
||||
"//fastpair/proto:fastpair_cc_proto",
|
||||
|
||||
@@ -120,7 +120,7 @@ void Retroactive::SetPairingStep(PairingStep step) {
|
||||
data_encryptor_.AddListener(
|
||||
[this](ExceptionOr<std::shared_ptr<FastPairDataEncryptor>> result) {
|
||||
if (result.ok() && result.result()) {
|
||||
SetPairingStep(PairingStep::kSendAccountKeyToProvider);
|
||||
SetPairingStep(PairingStep::kSendKeyBasedPairingRequest);
|
||||
} else {
|
||||
SetPairingStep(PairingStep::kFailed);
|
||||
}
|
||||
@@ -128,8 +128,8 @@ void Retroactive::SetPairingStep(PairingStep step) {
|
||||
&executor_);
|
||||
break;
|
||||
}
|
||||
case PairingStep::kSendAccountKeyToProvider: {
|
||||
// Open GATT connection and push the Account Key to provider.
|
||||
case PairingStep::kSendKeyBasedPairingRequest: {
|
||||
// Open GATT connection and send Key-based pairing request to provider.
|
||||
gatt_client_ = controller_->GetGattClientRef();
|
||||
gatt_client_.AddListener(
|
||||
[this](ExceptionOr<FastPairController::GattClientRef> gatt) {
|
||||
@@ -140,12 +140,11 @@ void Retroactive::SetPairingStep(PairingStep step) {
|
||||
NEARBY_LOGS(INFO) << "Sending Key Based Pairing request to "
|
||||
<< controller_->GetDevice().GetBleAddress();
|
||||
auto decryptor = data_encryptor_.Get().result().get();
|
||||
// TODO(jsobczak): Use real seeker address
|
||||
(gatt.result())
|
||||
->WriteRequestAsync(
|
||||
kKeyBasedPairingType, kRetroactiveFlags,
|
||||
controller_->GetDevice().GetBleAddress(), kSeekerAddress,
|
||||
*decryptor,
|
||||
controller_->GetDevice().GetBleAddress(),
|
||||
controller_->GetSeekerMacAddress(), *decryptor,
|
||||
[this](absl::string_view response,
|
||||
std::optional<PairFailure> failure) {
|
||||
if (failure.has_value()) {
|
||||
@@ -156,12 +155,32 @@ void Retroactive::SetPairingStep(PairingStep step) {
|
||||
}
|
||||
NEARBY_LOGS(INFO) << "key based pairing reply "
|
||||
<< absl::BytesToHexString(response);
|
||||
SetPairingStep(PairingStep::kAskForUserConfirmation);
|
||||
SetPairingStep(PairingStep::kSendAccountKeyToProvider);
|
||||
});
|
||||
},
|
||||
&executor_);
|
||||
break;
|
||||
}
|
||||
case PairingStep::kSendAccountKeyToProvider: {
|
||||
auto decryptor = data_encryptor_.Get().result().get();
|
||||
gatt_client_.Get().result()->WriteAccountKey(
|
||||
*decryptor, [this](std::optional<AccountKey> account_key,
|
||||
std::optional<PairFailure> failure) {
|
||||
if (failure.has_value()) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "Account key write failed with: " << *failure;
|
||||
SetPairingStep(PairingStep::kFailed);
|
||||
return;
|
||||
}
|
||||
DCHECK(account_key.has_value());
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Sent account key: "
|
||||
<< absl::BytesToHexString(account_key->GetAsBytes());
|
||||
controller_->GetDevice().SetAccountKey(*account_key);
|
||||
SetPairingStep(PairingStep::kAskForUserConfirmation);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case PairingStep::kAskForUserConfirmation: {
|
||||
// TODO(jsobczak): Display UI to ask the user to confirm onboarding the
|
||||
// device.
|
||||
|
||||
@@ -42,6 +42,7 @@ class Retroactive {
|
||||
kWaitForModelIdAndBleAddress,
|
||||
kFetchAntiSpoofingKey,
|
||||
kOpenGattConnection,
|
||||
kSendKeyBasedPairingRequest,
|
||||
kSendAccountKeyToProvider,
|
||||
kAskForUserConfirmation,
|
||||
kUploadAccountKeyToCloud,
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include "fastpair/retroactive/retroactive_pairing_detector_impl.h"
|
||||
|
||||
#include <ios>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "fastpair/internal/mediums/mediums.h"
|
||||
#include "fastpair/pairing/pairer_broker.h"
|
||||
@@ -23,9 +26,9 @@ namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
RetroactivePairingDetectorImpl::RetroactivePairingDetectorImpl(
|
||||
Mediums& mediums, PairerBroker* pairer_broker)
|
||||
: mediums_(mediums) {
|
||||
pairer_broker->AddObserver(this);
|
||||
Mediums& mediums, FastPairDeviceRepository* repository,
|
||||
SingleThreadExecutor* executor)
|
||||
: mediums_(mediums), repository_(repository), executor_(executor) {
|
||||
mediums_.GetBluetoothClassic().AddObserver(this);
|
||||
mediums_.GetBluetoothClassic().StartDiscovery();
|
||||
}
|
||||
@@ -45,30 +48,6 @@ void RetroactivePairingDetectorImpl::RemoveObserver(
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
void RetroactivePairingDetectorImpl::OnDevicePaired(FastPairDevice& device) {
|
||||
// The classic address is assigned to the Device during the
|
||||
// initial Fast Pair pairing protocol and if it doesn't exist,
|
||||
// then it wasn't properly paired during initial Fast Pair
|
||||
// pairing.
|
||||
if (!device.GetPublicAddress().has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The Bluetooth Adapter system event `DevicePairedChanged` fires before
|
||||
// Fast Pair's `OnDevicePaired`, and a Fast Pair pairing is expected to have
|
||||
// both events. If a device is Fast Paired, it is already inserted in the
|
||||
// |potential_retroactive_addresses_| in `DevicePairedChanged`; we need to
|
||||
// remove it to prevent a false positive.
|
||||
if (potential_retroactive_addresses_.contains(
|
||||
device.GetPublicAddress().value())) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__
|
||||
<< ": paired with initial pairing, removing device at address = "
|
||||
<< device.GetPublicAddress().value();
|
||||
potential_retroactive_addresses_.erase(device.GetPublicAddress().value());
|
||||
}
|
||||
}
|
||||
|
||||
void RetroactivePairingDetectorImpl::DevicePairedChanged(
|
||||
BluetoothDevice& device, bool new_paired_status) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
@@ -84,12 +63,13 @@ void RetroactivePairingDetectorImpl::DevicePairedChanged(
|
||||
return;
|
||||
}
|
||||
|
||||
// Both classic paired and Fast paired devices call this function, so we
|
||||
// have to add the device to |potential_retroactive_addresses_|. We expect
|
||||
// devices paired via Fast Pair to always call `OnDevicePaired` after calling
|
||||
// this function, which will remove the device from
|
||||
// |potential_retroactive_addresses_|.
|
||||
potential_retroactive_addresses_.insert(device.GetMacAddress());
|
||||
std::optional<FastPairDevice*> existing_device =
|
||||
repository_->FindDevice(device.GetMacAddress());
|
||||
if (existing_device.has_value()) {
|
||||
// Both classic paired and Fast paired devices call this function, so we
|
||||
// have to filter out pairing events for devices that we already know.
|
||||
return;
|
||||
}
|
||||
|
||||
// In order to confirm that this device is a retroactive pairing, we need to
|
||||
// first check if it has already been saved to the user's account. If it has
|
||||
@@ -98,7 +78,19 @@ void RetroactivePairingDetectorImpl::DevicePairedChanged(
|
||||
// TODO(b/285047010): check if device has already been saved to the user's
|
||||
// account
|
||||
|
||||
// TODO(Janusz) Add implementation for AttemptRetroactivePairing
|
||||
auto fast_pair_device =
|
||||
std::make_unique<FastPairDevice>(Protocol::kFastPairRetroactivePairing);
|
||||
fast_pair_device->SetPublicAddress(device.GetMacAddress());
|
||||
repository_->AddDevice(std::move(fast_pair_device));
|
||||
executor_->Execute("notify-retro-candidate",
|
||||
[this, address = device.GetMacAddress()]() {
|
||||
std::optional<FastPairDevice*> fast_pair_device =
|
||||
repository_->FindDevice(address);
|
||||
if (!fast_pair_device) return;
|
||||
for (auto observer : observers_.GetObservers()) {
|
||||
observer->OnRetroactivePairFound(**fast_pair_device);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -19,18 +19,22 @@
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "fastpair/internal/mediums/mediums.h"
|
||||
#include "fastpair/pairing/pairer_broker.h"
|
||||
#include "fastpair/repository/fast_pair_device_repository.h"
|
||||
#include "fastpair/retroactive/retroactive_pairing_detector.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/bluetooth_classic.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
class RetroactivePairingDetectorImpl : public RetroactivePairingDetector,
|
||||
public BluetoothClassicMedium ::Observer,
|
||||
public PairerBroker::Observer {
|
||||
class RetroactivePairingDetectorImpl
|
||||
: public RetroactivePairingDetector,
|
||||
public BluetoothClassicMedium ::Observer {
|
||||
public:
|
||||
RetroactivePairingDetectorImpl(Mediums& mediums, PairerBroker* pairer_broker);
|
||||
RetroactivePairingDetectorImpl(Mediums& mediums,
|
||||
FastPairDeviceRepository* repository,
|
||||
SingleThreadExecutor* executor);
|
||||
RetroactivePairingDetectorImpl(const RetroactivePairingDetectorImpl&) =
|
||||
delete;
|
||||
RetroactivePairingDetectorImpl& operator=(
|
||||
@@ -41,17 +45,15 @@ class RetroactivePairingDetectorImpl : public RetroactivePairingDetector,
|
||||
void AddObserver(RetroactivePairingDetector::Observer* observer) override;
|
||||
void RemoveObserver(RetroactivePairingDetector::Observer* observer) override;
|
||||
|
||||
// BluetoothClassicMedium :: Observer
|
||||
// BluetoothClassicMedium::Observer
|
||||
void DevicePairedChanged(BluetoothDevice& device,
|
||||
bool new_paired_status) override;
|
||||
|
||||
// PairerBroker::Observer
|
||||
void OnDevicePaired(FastPairDevice& device) override;
|
||||
|
||||
private:
|
||||
Mediums& mediums_;
|
||||
ObserverList<RetroactivePairingDetector::Observer> observers_;
|
||||
absl::flat_hash_set<std::string> potential_retroactive_addresses_;
|
||||
FastPairDeviceRepository* repository_;
|
||||
SingleThreadExecutor* executor_;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "fastpair/retroactive/retroactive.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "fastpair/message_stream/fake_gatt_callbacks.h"
|
||||
#include "fastpair/message_stream/fake_provider.h"
|
||||
#include "fastpair/proto/fastpair_rpcs.proto.h"
|
||||
@@ -34,7 +36,7 @@ namespace nearby {
|
||||
namespace fastpair {
|
||||
namespace {
|
||||
|
||||
constexpr char kModelId[] = {0xAB, 0xCD, 0xEF};
|
||||
constexpr char kModelId[] = "abcdef";
|
||||
constexpr absl::string_view kBobPrivateKey =
|
||||
"02B437B0EDD6BBD429064A4E529FCBF1C48D0D624924D592274B7ED81193D763";
|
||||
constexpr absl::string_view kBobPublicKey =
|
||||
@@ -58,6 +60,9 @@ class RetroactiveTest : public testing::Test {
|
||||
provider_.StartGattServer(&gatt_callbacks_);
|
||||
provider_.InsertCorrectGattCharacteristics();
|
||||
ASSERT_TRUE(remote_device_.IsValid());
|
||||
fast_pair_device_ =
|
||||
std::make_unique<FastPairDevice>(Protocol::kFastPairRetroactivePairing);
|
||||
fast_pair_device_->SetPublicAddress(remote_device_.GetMacAddress());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
@@ -83,20 +88,23 @@ class RetroactiveTest : public testing::Test {
|
||||
BluetoothDevice remote_device_;
|
||||
FakeFastPairRepository repository_;
|
||||
FakeGattCallbacks gatt_callbacks_;
|
||||
std::unique_ptr<FastPairDevice> fast_pair_device_;
|
||||
};
|
||||
|
||||
TEST_F(RetroactiveTest, Constructor) {
|
||||
FastPairController controller(&mediums_, remote_device_, &executor_);
|
||||
FastPairController controller(&mediums_, &*fast_pair_device_, &executor_);
|
||||
Retroactive retro(&controller);
|
||||
}
|
||||
|
||||
TEST_F(RetroactiveTest, Pair) {
|
||||
SetUpFastPairRepository(kModelId, absl::HexStringToBytes(kBobPublicKey));
|
||||
FastPairController controller(&mediums_, remote_device_, &executor_);
|
||||
FastPairController controller(&mediums_, &*fast_pair_device_, &executor_);
|
||||
provider_.EnableProviderRfcomm();
|
||||
provider_.LoadAntiSpoofingKey(absl::HexStringToBytes(kBobPrivateKey),
|
||||
absl::HexStringToBytes(kBobPublicKey));
|
||||
std::string provider_ble_address = provider_.GetMacAddressAsBytes();
|
||||
std::string seeker_address =
|
||||
std::string(BluetoothUtils::FromString(controller.GetSeekerMacAddress()));
|
||||
gatt_callbacks_.characteristics_[*provider_.key_based_characteristic_]
|
||||
.write_callback = [&](absl::string_view request) {
|
||||
// https://developers.google.com/nearby/fast-pair/specifications/characteristics#table1.1
|
||||
@@ -106,9 +114,8 @@ TEST_F(RetroactiveTest, Pair) {
|
||||
// Bytes 2 - 7, aabbccddeeff, provider's address
|
||||
// Bytes 8 - 13, 111213141516, seeker's address
|
||||
// Bytes 14 - 15, (not included), random salt
|
||||
std::string expected_kbp_request = absl::HexStringToBytes("0010") +
|
||||
provider_ble_address +
|
||||
absl::HexStringToBytes("111213141516");
|
||||
std::string expected_kbp_request =
|
||||
absl::HexStringToBytes("0010") + provider_ble_address + seeker_address;
|
||||
|
||||
// https://developers.google.com/nearby/fast-pair/specifications/characteristics#table1.2.2
|
||||
// Byte 0, 0x01 = Key-based Pairing Response
|
||||
@@ -143,6 +150,12 @@ TEST_F(RetroactiveTest, Pair) {
|
||||
provider_ble_address);
|
||||
|
||||
EXPECT_TRUE(result.Get(absl::Minutes(5)).ok());
|
||||
EXPECT_EQ(
|
||||
gatt_callbacks_.characteristics_[*provider_.accountkey_characteristic_]
|
||||
.write_value.Get()
|
||||
.result()
|
||||
.size(),
|
||||
kAccountKeySize);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user