From e00bdfb3e304f435451c56db78bcbb58e4ef5835 Mon Sep 17 00:00:00 2001 From: Janusz Sobczak Date: Fri, 30 Jun 2023 04:05:28 -0700 Subject: [PATCH] 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 --- fastpair/BUILD | 1 + fastpair/fast_pair_controller.cc | 51 ++++++++-------- fastpair/fast_pair_controller.h | 9 ++- fastpair/fast_pair_controller_test.cc | 9 ++- fastpair/internal/BUILD | 3 +- fastpair/internal/fast_pair_seeker_impl.cc | 37 ++++++++++-- fastpair/internal/fast_pair_seeker_impl.h | 12 +++- .../internal/fast_pair_seeker_impl_test.cc | 34 +++++++++++ fastpair/message_stream/fake_provider.cc | 51 ++++++++++++++++ fastpair/message_stream/fake_provider.h | 8 +++ fastpair/retroactive/BUILD | 2 + fastpair/retroactive/retroactive.cc | 33 +++++++--- fastpair/retroactive/retroactive.h | 1 + .../retroactive_pairing_detector_impl.cc | 60 ++++++++----------- .../retroactive_pairing_detector_impl.h | 20 ++++--- fastpair/retroactive/retroactive_test.cc | 25 ++++++-- 16 files changed, 260 insertions(+), 96 deletions(-) diff --git a/fastpair/BUILD b/fastpair/BUILD index f4285b79..248cddf5 100644 --- a/fastpair/BUILD +++ b/fastpair/BUILD @@ -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", ], ) diff --git a/fastpair/fast_pair_controller.cc b/fastpair/fast_pair_controller.cc index 40406930..cf3b6ce4 100644 --- a/fastpair/fast_pair_controller.cc +++ b/fastpair/fast_pair_controller.cc @@ -21,6 +21,7 @@ #include #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( - 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>>(); - 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 encryptor) mutable { + *device_, [borrowable = lender_.GetBorrowable()]( + std::unique_ptr 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 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); } } diff --git a/fastpair/fast_pair_controller.h b/fastpair/fast_pair_controller.h index b4dac03f..bcf69bd6 100644 --- a/fastpair/fast_pair_controller.h +++ b/fastpair/fast_pair_controller.h @@ -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 encryptor) { @@ -177,7 +180,7 @@ class FastPairController : public MessageStream::Observer { } void CreateDataEncryptor(); Mediums* mediums_; - FastPairDevice device_; + FastPairDevice* device_; SingleThreadExecutor* executor_; std::unique_ptr>> encryptor_; std::unique_ptr message_stream_; diff --git a/fastpair/fast_pair_controller_test.cc b/fastpair/fast_pair_controller_test.cc index 496c59a3..53d9642d 100644 --- a/fastpair/fast_pair_controller_test.cc +++ b/fastpair/fast_pair_controller_test.cc @@ -14,6 +14,7 @@ #include "fastpair/fast_pair_controller.h" +#include #include #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(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 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()); } diff --git a/fastpair/internal/BUILD b/fastpair/internal/BUILD index d02168ef..72516d51 100644 --- a/fastpair/internal/BUILD +++ b/fastpair/internal/BUILD @@ -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", ], diff --git a/fastpair/internal/fast_pair_seeker_impl.cc b/fastpair/internal/fast_pair_seeker_impl.cc index dd903fe1..f719a7ef 100644 --- a/fastpair/internal/fast_pair_seeker_impl.cc +++ b/fastpair/internal/fast_pair_seeker_impl.cc @@ -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(mediums_, executor_); pairer_broker_->AddObserver(this); mediums_.GetBluetoothClassic().AddObserver(this); + retro_detector_ = std::make_unique( + 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(device); + controller_ = std::make_unique( + &mediums_, device_under_pairing_, executor_); + retroactive_pair_ = std::make_unique(controller_.get()); + pairing_callback_ = std::make_unique(std::move(callback)); + retroactive_pair_->Pair().AddListener( + [this](ExceptionOr 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 diff --git a/fastpair/internal/fast_pair_seeker_impl.h b/fastpair/internal/fast_pair_seeker_impl.h index c029bac8..968828ed 100644 --- a/fastpair/internal/fast_pair_seeker_impl.h +++ b/fastpair/internal/fast_pair_seeker_impl.h @@ -19,11 +19,14 @@ #include #include +#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 @@ -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 scanning_session_; std::unique_ptr pairer_broker_; std::unique_ptr pairing_callback_; + std::unique_ptr retro_detector_; + std::unique_ptr controller_; + std::unique_ptr retroactive_pair_; FastPairDevice* device_under_pairing_ = nullptr; FastPairDevice* test_device_ = nullptr; bool is_screen_locked_ = false; diff --git a/fastpair/internal/fast_pair_seeker_impl_test.cc b/fastpair/internal/fast_pair_seeker_impl_test.cc index cc2fe7b0..28f22ced 100644 --- a/fastpair/internal/fast_pair_seeker_impl_test.cc +++ b/fastpair/internal/fast_pair_seeker_impl_test.cc @@ -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::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 diff --git a/fastpair/message_stream/fake_provider.cc b/fastpair/message_stream/fake_provider.cc index 4116ba13..2c7030bd 100644 --- a/fastpair/message_stream/fake_provider.cc +++ b/fastpair/message_stream/fake_provider.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "fastpair/message_stream/fake_provider.h" +#include #include #include @@ -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 #include @@ -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 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 diff --git a/fastpair/message_stream/fake_provider.h b/fastpair/message_stream/fake_provider.h index 7813cb5b..47bd2bb2 100644 --- a/fastpair/message_stream/fake_provider.h +++ b/fastpair/message_stream/fake_provider.h @@ -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_; diff --git a/fastpair/retroactive/BUILD b/fastpair/retroactive/BUILD index fe9fe81a..ff25a0c0 100644 --- a/fastpair/retroactive/BUILD +++ b/fastpair/retroactive/BUILD @@ -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", diff --git a/fastpair/retroactive/retroactive.cc b/fastpair/retroactive/retroactive.cc index 44597c61..4581723a 100644 --- a/fastpair/retroactive/retroactive.cc +++ b/fastpair/retroactive/retroactive.cc @@ -120,7 +120,7 @@ void Retroactive::SetPairingStep(PairingStep step) { data_encryptor_.AddListener( [this](ExceptionOr> 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 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 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 account_key, + std::optional 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. diff --git a/fastpair/retroactive/retroactive.h b/fastpair/retroactive/retroactive.h index ebf09d28..c46e62f6 100644 --- a/fastpair/retroactive/retroactive.h +++ b/fastpair/retroactive/retroactive.h @@ -42,6 +42,7 @@ class Retroactive { kWaitForModelIdAndBleAddress, kFetchAntiSpoofingKey, kOpenGattConnection, + kSendKeyBasedPairingRequest, kSendAccountKeyToProvider, kAskForUserConfirmation, kUploadAccountKeyToCloud, diff --git a/fastpair/retroactive/retroactive_pairing_detector_impl.cc b/fastpair/retroactive/retroactive_pairing_detector_impl.cc index 1464fe12..4aae90c5 100644 --- a/fastpair/retroactive/retroactive_pairing_detector_impl.cc +++ b/fastpair/retroactive/retroactive_pairing_detector_impl.cc @@ -15,6 +15,9 @@ #include "fastpair/retroactive/retroactive_pairing_detector_impl.h" #include +#include +#include +#include #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 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(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 fast_pair_device = + repository_->FindDevice(address); + if (!fast_pair_device) return; + for (auto observer : observers_.GetObservers()) { + observer->OnRetroactivePairFound(**fast_pair_device); + } + }); } } // namespace fastpair diff --git a/fastpair/retroactive/retroactive_pairing_detector_impl.h b/fastpair/retroactive/retroactive_pairing_detector_impl.h index e4baef38..a24d0617 100644 --- a/fastpair/retroactive/retroactive_pairing_detector_impl.h +++ b/fastpair/retroactive/retroactive_pairing_detector_impl.h @@ -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 observers_; - absl::flat_hash_set potential_retroactive_addresses_; + FastPairDeviceRepository* repository_; + SingleThreadExecutor* executor_; }; } // namespace fastpair diff --git a/fastpair/retroactive/retroactive_test.cc b/fastpair/retroactive/retroactive_test.cc index 65406496..477ec90f 100644 --- a/fastpair/retroactive/retroactive_test.cc +++ b/fastpair/retroactive/retroactive_test.cc @@ -14,6 +14,7 @@ #include "fastpair/retroactive/retroactive.h" +#include #include #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(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 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