Reland "[Fast Pair] Add support for retroactive pairing for BLE HID"
This is a reland of commit 0b3859cd0d
and fixes test failures on MSAN builder.
Original change's description:
> [Fast Pair] Add support for retroactive pairing for BLE HID
>
> For BLE devices, since we cannot connect to a message stream to
> retrieve the model ID and the BLE address is already known, the
> only remaining parameter needed is the model ID, which we
> retrieve via GATT characteristic
>
> BUG=b:308092093
> TEST=unit tests
> TEST=manually test initial and retroactive pairing for HID
>
> Change-Id: Ic93cffff190b5927f49e00d23e0781dd1c04efe0
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4995811
> Reviewed-by: Reilly Grant <reillyg@chromium.org>
> Reviewed-by: Jack Shira <jackshira@google.com>
> Commit-Queue: Katherine Lai <laikatherine@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1224991}
BUG=b:308092093
TEST=MSAN browser_tests
TEST=ash_unittests
Change-Id: I941e3ee4fc1c90858f01d71bb1b7da988b59f366
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5038291
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Katherine Lai <laikatherine@chromium.org>
Reviewed-by: Jack Shira <jackshira@google.com>
Cr-Commit-Position: refs/heads/main@{#1225663}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
3a214002ca
commit
619c703d95
ash/quick_pair/pairing
retroactive_pairing_detector_impl.ccretroactive_pairing_detector_impl.hretroactive_pairing_detector_unittest.cc
device/bluetooth/test
@@ -9,6 +9,7 @@
|
|||||||
#include "ash/quick_pair/common/constants.h"
|
#include "ash/quick_pair/common/constants.h"
|
||||||
#include "ash/quick_pair/common/device.h"
|
#include "ash/quick_pair/common/device.h"
|
||||||
#include "ash/quick_pair/common/protocol.h"
|
#include "ash/quick_pair/common/protocol.h"
|
||||||
|
#include "ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_lookup_impl.h"
|
||||||
#include "ash/quick_pair/message_stream/message_stream.h"
|
#include "ash/quick_pair/message_stream/message_stream.h"
|
||||||
#include "ash/quick_pair/repository/fast_pair_repository.h"
|
#include "ash/quick_pair/repository/fast_pair_repository.h"
|
||||||
#include "ash/session/session_controller_impl.h"
|
#include "ash/session/session_controller_impl.h"
|
||||||
@@ -219,8 +220,27 @@ void RetroactivePairingDetectorImpl::AttemptRetroactivePairing(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device::BluetoothDevice* device = adapter_->GetDevice(classic_address);
|
||||||
|
if (!device) {
|
||||||
|
CD_LOG(WARNING, Feature::FP)
|
||||||
|
<< __func__ << ": Lost device to potentially retroactively pair to.";
|
||||||
|
RemoveDeviceInformation(classic_address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CD_LOG(VERBOSE, Feature::FP) << __func__ << ": device = " << classic_address;
|
CD_LOG(VERBOSE, Feature::FP) << __func__ << ": device = " << classic_address;
|
||||||
|
|
||||||
|
// For BLE devices, since we cannot connect to a message stream to retrieve
|
||||||
|
// the model ID and the BLE address is already known, the only remaining
|
||||||
|
// parameter needed is the model ID, which we retrieve via GATT characteristic
|
||||||
|
if (ash::features::IsFastPairHIDEnabled() &&
|
||||||
|
device->GetType() == device::BLUETOOTH_TRANSPORT_LE) {
|
||||||
|
CD_LOG(VERBOSE, Feature::FP)
|
||||||
|
<< __func__ << ": BLE device detected, creating GATT connection";
|
||||||
|
CreateGattConnection(device);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to retrieve a MessageStream instance immediately, if it was
|
// Attempt to retrieve a MessageStream instance immediately, if it was
|
||||||
// already connected.
|
// already connected.
|
||||||
MessageStream* message_stream =
|
MessageStream* message_stream =
|
||||||
@@ -232,6 +252,98 @@ void RetroactivePairingDetectorImpl::AttemptRetroactivePairing(
|
|||||||
GetModelIdAndAddressFromMessageStream(classic_address, message_stream);
|
GetModelIdAndAddressFromMessageStream(classic_address, message_stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RetroactivePairingDetectorImpl::CreateGattConnection(
|
||||||
|
device::BluetoothDevice* device) {
|
||||||
|
auto* fast_pair_gatt_service_client =
|
||||||
|
FastPairGattServiceClientLookup::GetInstance()->Get(device);
|
||||||
|
|
||||||
|
if (fast_pair_gatt_service_client) {
|
||||||
|
if (fast_pair_gatt_service_client->IsConnected()) {
|
||||||
|
CD_LOG(VERBOSE, Feature::FP)
|
||||||
|
<< __func__
|
||||||
|
<< ": Reusing existing GATT service client to retrieve model ID";
|
||||||
|
fast_pair_gatt_service_client->ReadModelIdAsync(
|
||||||
|
base::BindOnce(&RetroactivePairingDetectorImpl::OnReadModelId,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), device->GetAddress()));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// If the previous gatt service client did not connect successfully
|
||||||
|
// or is no longer connected, erase it before attempting to create a new
|
||||||
|
// gatt connection for the device.
|
||||||
|
FastPairGattServiceClientLookup::GetInstance()->Erase(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CD_LOG(VERBOSE, Feature::FP)
|
||||||
|
<< __func__ << ": Creating new GATT service client to retrieve model ID";
|
||||||
|
|
||||||
|
FastPairGattServiceClientLookup::GetInstance()->Create(
|
||||||
|
adapter_, device,
|
||||||
|
base::BindOnce(
|
||||||
|
&RetroactivePairingDetectorImpl::OnGattClientInitializedCallback,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), device));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RetroactivePairingDetectorImpl::OnGattClientInitializedCallback(
|
||||||
|
device::BluetoothDevice* device,
|
||||||
|
absl::optional<PairFailure> failure) {
|
||||||
|
if (failure) {
|
||||||
|
CD_LOG(WARNING, Feature::FP)
|
||||||
|
<< __func__
|
||||||
|
<< ": Failed to initialize GATT service client with failure = "
|
||||||
|
<< failure.value();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If |OnGattClientInitializedCallback| is called without a failure,
|
||||||
|
// |device*| is expected to exist and be valid.
|
||||||
|
auto* fast_pair_gatt_service_client =
|
||||||
|
FastPairGattServiceClientLookup::GetInstance()->Get(device);
|
||||||
|
|
||||||
|
if (!fast_pair_gatt_service_client ||
|
||||||
|
!fast_pair_gatt_service_client->IsConnected()) {
|
||||||
|
CD_LOG(WARNING, Feature::FP) << __func__
|
||||||
|
<< ": Fast Pair Gatt Service Client failed to "
|
||||||
|
"be created or is no longer connected.";
|
||||||
|
FastPairGattServiceClientLookup::GetInstance()->Erase(device);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CD_LOG(VERBOSE, Feature::FP) << __func__
|
||||||
|
<< ": Fast Pair GATT service client initialized "
|
||||||
|
"successfully. Reading Model ID.";
|
||||||
|
|
||||||
|
fast_pair_gatt_service_client->ReadModelIdAsync(
|
||||||
|
base::BindOnce(&RetroactivePairingDetectorImpl::OnReadModelId,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), device->GetAddress()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RetroactivePairingDetectorImpl::OnReadModelId(
|
||||||
|
const std::string& address,
|
||||||
|
absl::optional<device::BluetoothGattService::GattErrorCode> error_code,
|
||||||
|
const std::vector<uint8_t>& value) {
|
||||||
|
if (error_code) {
|
||||||
|
CD_LOG(WARNING, Feature::FP)
|
||||||
|
<< __func__ << ": Failed to read model ID with failure = "
|
||||||
|
<< static_cast<uint32_t>(error_code.value());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.size() != 3) {
|
||||||
|
CD_LOG(WARNING, Feature::FP) << __func__ << ": model ID malformed.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string model_id;
|
||||||
|
for (auto byte : value) {
|
||||||
|
model_id.append(base::StringPrintf("%02X", byte));
|
||||||
|
}
|
||||||
|
|
||||||
|
CD_LOG(INFO, Feature::FP) << __func__ << ": Model ID " << model_id
|
||||||
|
<< " found for device " << address;
|
||||||
|
NotifyDeviceFound(model_id, address, address);
|
||||||
|
}
|
||||||
|
|
||||||
void RetroactivePairingDetectorImpl::OnMessageStreamConnected(
|
void RetroactivePairingDetectorImpl::OnMessageStreamConnected(
|
||||||
const std::string& device_address,
|
const std::string& device_address,
|
||||||
MessageStream* message_stream) {
|
MessageStream* message_stream) {
|
||||||
|
@@ -158,6 +158,19 @@ class RetroactivePairingDetectorImpl final
|
|||||||
// |message_streams_| if a MessageStream exists for the device.
|
// |message_streams_| if a MessageStream exists for the device.
|
||||||
void RemoveExpiredDevicesFromStoredDeviceData();
|
void RemoveExpiredDevicesFromStoredDeviceData();
|
||||||
|
|
||||||
|
// Gets or creates a Gatt connection to |device|.
|
||||||
|
void CreateGattConnection(device::BluetoothDevice* device);
|
||||||
|
|
||||||
|
// Internal method called when creating a FastPairGattServiceClient.
|
||||||
|
void OnGattClientInitializedCallback(device::BluetoothDevice* device,
|
||||||
|
absl::optional<PairFailure> failure);
|
||||||
|
|
||||||
|
// Internal method called to retrieve the model ID of a device.
|
||||||
|
void OnReadModelId(
|
||||||
|
const std::string& address,
|
||||||
|
absl::optional<device::BluetoothGattService::GattErrorCode> error_code,
|
||||||
|
const std::vector<uint8_t>& value);
|
||||||
|
|
||||||
// The classic pairing addresses of potential Retroactive Pair supported
|
// The classic pairing addresses of potential Retroactive Pair supported
|
||||||
// devices that are found in the adapter. We have to store them and wait for a
|
// devices that are found in the adapter. We have to store them and wait for a
|
||||||
// MessageStream instance to be created for the device in order to fully
|
// MessageStream instance to be created for the device in order to fully
|
||||||
|
@@ -13,6 +13,9 @@
|
|||||||
#include "ash/quick_pair/common/logging.h"
|
#include "ash/quick_pair/common/logging.h"
|
||||||
#include "ash/quick_pair/common/pair_failure.h"
|
#include "ash/quick_pair/common/pair_failure.h"
|
||||||
#include "ash/quick_pair/common/protocol.h"
|
#include "ash/quick_pair/common/protocol.h"
|
||||||
|
#include "ash/quick_pair/fast_pair_handshake/fake_fast_pair_gatt_service_client.h"
|
||||||
|
#include "ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.h"
|
||||||
|
#include "ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_lookup_impl.h"
|
||||||
#include "ash/quick_pair/message_stream/fake_bluetooth_socket.h"
|
#include "ash/quick_pair/message_stream/fake_bluetooth_socket.h"
|
||||||
#include "ash/quick_pair/message_stream/fake_message_stream_lookup.h"
|
#include "ash/quick_pair/message_stream/fake_message_stream_lookup.h"
|
||||||
#include "ash/quick_pair/message_stream/message_stream.h"
|
#include "ash/quick_pair/message_stream/message_stream.h"
|
||||||
@@ -56,6 +59,7 @@ const std::vector<uint8_t> kModelIdBytes = {
|
|||||||
/*message_code=*/0x01,
|
/*message_code=*/0x01,
|
||||||
/*additional_data_length=*/0x00, 0x03,
|
/*additional_data_length=*/0x00, 0x03,
|
||||||
/*additional_data=*/0xAA, 0xBB, 0xCC};
|
/*additional_data=*/0xAA, 0xBB, 0xCC};
|
||||||
|
const std::vector<uint8_t> kModelIdBytesNoMetadata = {0xAA, 0xBB, 0xCC};
|
||||||
const std::string kModelId = "AABBCC";
|
const std::string kModelId = "AABBCC";
|
||||||
|
|
||||||
const std::vector<uint8_t> kBleAddressBytes = {
|
const std::vector<uint8_t> kBleAddressBytes = {
|
||||||
@@ -97,6 +101,36 @@ CreateTestBluetoothDevice(std::string address) {
|
|||||||
/*paired=*/true, /*connected=*/false);
|
/*paired=*/true, /*connected=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FakeFastPairGattServiceClientImplFactory
|
||||||
|
: public ash::quick_pair::FastPairGattServiceClientImpl::Factory {
|
||||||
|
public:
|
||||||
|
~FakeFastPairGattServiceClientImplFactory() override = default;
|
||||||
|
|
||||||
|
ash::quick_pair::FakeFastPairGattServiceClient*
|
||||||
|
fake_fast_pair_gatt_service_client() {
|
||||||
|
return fake_fast_pair_gatt_service_client_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// FastPairGattServiceClientImpl::Factory:
|
||||||
|
std::unique_ptr<ash::quick_pair::FastPairGattServiceClient> CreateInstance(
|
||||||
|
device::BluetoothDevice* device,
|
||||||
|
scoped_refptr<device::BluetoothAdapter> adapter,
|
||||||
|
base::OnceCallback<void(absl::optional<ash::quick_pair::PairFailure>)>
|
||||||
|
on_initialized_callback) override {
|
||||||
|
auto fake_fast_pair_gatt_service_client =
|
||||||
|
std::make_unique<ash::quick_pair::FakeFastPairGattServiceClient>(
|
||||||
|
device, adapter, std::move(on_initialized_callback));
|
||||||
|
fake_fast_pair_gatt_service_client_ =
|
||||||
|
fake_fast_pair_gatt_service_client.get();
|
||||||
|
return fake_fast_pair_gatt_service_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_ptr<ash::quick_pair::FakeFastPairGattServiceClient,
|
||||||
|
DanglingUntriaged | ExperimentalAsh>
|
||||||
|
fake_fast_pair_gatt_service_client_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace ash {
|
namespace ash {
|
||||||
@@ -111,6 +145,9 @@ class RetroactivePairingDetectorTest
|
|||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
AshTestBase::SetUp();
|
AshTestBase::SetUp();
|
||||||
|
FastPairGattServiceClientImpl::Factory::SetFactoryForTesting(
|
||||||
|
&fast_pair_gatt_service_factory_);
|
||||||
|
|
||||||
adapter_ = base::MakeRefCounted<FakeBluetoothAdapter>();
|
adapter_ = base::MakeRefCounted<FakeBluetoothAdapter>();
|
||||||
device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
|
device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
|
||||||
|
|
||||||
@@ -168,11 +205,23 @@ class RetroactivePairingDetectorTest
|
|||||||
mock_pairer_broker_->NotifyDevicePaired(fp_device);
|
mock_pairer_broker_->NotifyDevicePaired(fp_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PairFastPairDeviceWithClassicBluetooth(bool new_paired_status,
|
void PairFastPairDeviceWithClassicBluetooth(
|
||||||
std::string classic_address) {
|
bool new_paired_status,
|
||||||
|
std::string classic_address,
|
||||||
|
bool test_hid_already_connected = false) {
|
||||||
bluetooth_device_ = CreateTestBluetoothDevice(classic_address);
|
bluetooth_device_ = CreateTestBluetoothDevice(classic_address);
|
||||||
bluetooth_device_->AddUUID(ash::quick_pair::kFastPairBluetoothUuid);
|
bluetooth_device_->AddUUID(ash::quick_pair::kFastPairBluetoothUuid);
|
||||||
|
bluetooth_device_->SetType(
|
||||||
|
device::BluetoothTransport::BLUETOOTH_TRANSPORT_LE);
|
||||||
auto* bt_device_ptr = bluetooth_device_.get();
|
auto* bt_device_ptr = bluetooth_device_.get();
|
||||||
|
if (test_hid_already_connected) {
|
||||||
|
// Simulate a GATT service client connection already open and connected
|
||||||
|
auto gatt_service_client = FastPairGattServiceClientImpl::Factory::Create(
|
||||||
|
bt_device_ptr, adapter_.get(), base::DoNothing());
|
||||||
|
FastPairGattServiceClientLookup::GetInstance()->InsertFakeForTesting(
|
||||||
|
bt_device_ptr, std::move(gatt_service_client));
|
||||||
|
SetGattServiceClientConnected(true);
|
||||||
|
}
|
||||||
adapter_->AddMockDevice(std::move(bluetooth_device_));
|
adapter_->AddMockDevice(std::move(bluetooth_device_));
|
||||||
adapter_->NotifyDevicePairedChanged(bt_device_ptr, new_paired_status);
|
adapter_->NotifyDevicePairedChanged(bt_device_ptr, new_paired_status);
|
||||||
}
|
}
|
||||||
@@ -200,6 +249,24 @@ class RetroactivePairingDetectorTest
|
|||||||
SimulateUserLogin(kUserEmail, user_type);
|
SimulateUserLogin(kUserEmail, user_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetGattServiceClientConnected(bool connected) {
|
||||||
|
fast_pair_gatt_service_factory_.fake_fast_pair_gatt_service_client()
|
||||||
|
->SetConnected(connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunGattClientInitializedCallback(
|
||||||
|
absl::optional<PairFailure> pair_failure) {
|
||||||
|
fast_pair_gatt_service_factory_.fake_fast_pair_gatt_service_client()
|
||||||
|
->RunOnGattClientInitializedCallback(pair_failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunReadModelIdCallback(
|
||||||
|
absl::optional<device::BluetoothGattService::GattErrorCode> error_code,
|
||||||
|
const std::vector<uint8_t>& value) {
|
||||||
|
fast_pair_gatt_service_factory_.fake_fast_pair_gatt_service_client()
|
||||||
|
->RunReadModelIdCallback(error_code, value);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool retroactive_pair_found_ = false;
|
bool retroactive_pair_found_ = false;
|
||||||
scoped_refptr<Device> retroactive_device_;
|
scoped_refptr<Device> retroactive_device_;
|
||||||
@@ -216,6 +283,8 @@ class RetroactivePairingDetectorTest
|
|||||||
fake_message_stream_lookup_ = nullptr;
|
fake_message_stream_lookup_ = nullptr;
|
||||||
std::unique_ptr<FakeFastPairRepository> fast_pair_repository_;
|
std::unique_ptr<FakeFastPairRepository> fast_pair_repository_;
|
||||||
|
|
||||||
|
FakeFastPairGattServiceClientImplFactory fast_pair_gatt_service_factory_;
|
||||||
|
|
||||||
mojo::SharedRemote<mojom::FastPairDataParser> data_parser_remote_;
|
mojo::SharedRemote<mojom::FastPairDataParser> data_parser_remote_;
|
||||||
mojo::PendingRemote<mojom::FastPairDataParser> fast_pair_data_parser_;
|
mojo::PendingRemote<mojom::FastPairDataParser> fast_pair_data_parser_;
|
||||||
std::unique_ptr<FastPairDataParser> data_parser_;
|
std::unique_ptr<FastPairDataParser> data_parser_;
|
||||||
@@ -2078,5 +2147,112 @@ TEST_F(RetroactivePairingDetectorTest, NoCrashWhenFootprintsResponseIsSlow) {
|
|||||||
fast_pair_repository_->TriggerIsDeviceSavedToAccountCallback();
|
fast_pair_repository_->TriggerIsDeviceSavedToAccountCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RetroactivePairingDetectorTest, FastPairHID_Success) {
|
||||||
|
Login(user_manager::UserType::USER_TYPE_REGULAR);
|
||||||
|
base::test::ScopedFeatureList feature_list;
|
||||||
|
feature_list.InitWithFeatures(
|
||||||
|
/*enabled_features=*/{features::kFastPairSavedDevices,
|
||||||
|
features::kFastPairSavedDevicesStrictOptIn,
|
||||||
|
features::kFastPairHID},
|
||||||
|
/*disabled_features=*/{});
|
||||||
|
fast_pair_repository_->SetOptInStatus(
|
||||||
|
nearby::fastpair::OptInStatus::STATUS_OPTED_IN);
|
||||||
|
base::RunLoop().RunUntilIdle();
|
||||||
|
CreateRetroactivePairingDetector();
|
||||||
|
|
||||||
|
EXPECT_FALSE(retroactive_pair_found_);
|
||||||
|
|
||||||
|
// Test the normal retroactive pair flow of a BLE HID
|
||||||
|
PairFastPairDeviceWithClassicBluetooth(
|
||||||
|
/*new_paired_status=*/true, kBleAddress);
|
||||||
|
SetGattServiceClientConnected(true);
|
||||||
|
RunGattClientInitializedCallback(/*pair_failure=*/absl::nullopt);
|
||||||
|
RunReadModelIdCallback(/*error_code=*/absl::nullopt, kModelIdBytesNoMetadata);
|
||||||
|
|
||||||
|
EXPECT_TRUE(retroactive_pair_found_);
|
||||||
|
EXPECT_EQ(retroactive_device_->ble_address(), kBleAddress);
|
||||||
|
EXPECT_EQ(retroactive_device_->metadata_id(), kModelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RetroactivePairingDetectorTest, FastPairHID_GattConnectionOpen_Success) {
|
||||||
|
Login(user_manager::UserType::USER_TYPE_REGULAR);
|
||||||
|
base::test::ScopedFeatureList feature_list;
|
||||||
|
feature_list.InitWithFeatures(
|
||||||
|
/*enabled_features=*/{features::kFastPairSavedDevices,
|
||||||
|
features::kFastPairSavedDevicesStrictOptIn,
|
||||||
|
features::kFastPairHID},
|
||||||
|
/*disabled_features=*/{});
|
||||||
|
fast_pair_repository_->SetOptInStatus(
|
||||||
|
nearby::fastpair::OptInStatus::STATUS_OPTED_IN);
|
||||||
|
base::RunLoop().RunUntilIdle();
|
||||||
|
CreateRetroactivePairingDetector();
|
||||||
|
|
||||||
|
EXPECT_FALSE(retroactive_pair_found_);
|
||||||
|
|
||||||
|
// If GATT connection already open, we expect a read to Model ID
|
||||||
|
// immediately after.
|
||||||
|
PairFastPairDeviceWithClassicBluetooth(
|
||||||
|
/*new_paired_status=*/true, kBleAddress,
|
||||||
|
/*test_hid_already_connected=*/true);
|
||||||
|
RunReadModelIdCallback(/*error_code*/ absl::nullopt, kModelIdBytesNoMetadata);
|
||||||
|
|
||||||
|
EXPECT_TRUE(retroactive_pair_found_);
|
||||||
|
EXPECT_EQ(retroactive_device_->ble_address(), kBleAddress);
|
||||||
|
EXPECT_EQ(retroactive_device_->metadata_id(), kModelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RetroactivePairingDetectorTest, FastPairHID_GattConnectionFailure) {
|
||||||
|
Login(user_manager::UserType::USER_TYPE_REGULAR);
|
||||||
|
base::test::ScopedFeatureList feature_list;
|
||||||
|
feature_list.InitWithFeatures(
|
||||||
|
/*enabled_features=*/{features::kFastPairSavedDevices,
|
||||||
|
features::kFastPairSavedDevicesStrictOptIn,
|
||||||
|
features::kFastPairHID},
|
||||||
|
/*disabled_features=*/{});
|
||||||
|
fast_pair_repository_->SetOptInStatus(
|
||||||
|
nearby::fastpair::OptInStatus::STATUS_OPTED_IN);
|
||||||
|
base::RunLoop().RunUntilIdle();
|
||||||
|
CreateRetroactivePairingDetector();
|
||||||
|
|
||||||
|
EXPECT_FALSE(retroactive_pair_found_);
|
||||||
|
|
||||||
|
PairFastPairDeviceWithClassicBluetooth(
|
||||||
|
/*new_paired_status=*/true, kBleAddress);
|
||||||
|
SetGattServiceClientConnected(true);
|
||||||
|
|
||||||
|
// If we get an error while create the GATT connection, we shouldn't
|
||||||
|
// expect a retroactive pairable device to be found.
|
||||||
|
RunGattClientInitializedCallback(PairFailure::kCreateGattConnection);
|
||||||
|
EXPECT_FALSE(retroactive_pair_found_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RetroactivePairingDetectorTest, FastPairHID_ReadModelIdFailure) {
|
||||||
|
Login(user_manager::UserType::USER_TYPE_REGULAR);
|
||||||
|
base::test::ScopedFeatureList feature_list;
|
||||||
|
feature_list.InitWithFeatures(
|
||||||
|
/*enabled_features=*/{features::kFastPairSavedDevices,
|
||||||
|
features::kFastPairSavedDevicesStrictOptIn,
|
||||||
|
features::kFastPairHID},
|
||||||
|
/*disabled_features=*/{});
|
||||||
|
fast_pair_repository_->SetOptInStatus(
|
||||||
|
nearby::fastpair::OptInStatus::STATUS_OPTED_IN);
|
||||||
|
base::RunLoop().RunUntilIdle();
|
||||||
|
CreateRetroactivePairingDetector();
|
||||||
|
|
||||||
|
EXPECT_FALSE(retroactive_pair_found_);
|
||||||
|
|
||||||
|
PairFastPairDeviceWithClassicBluetooth(
|
||||||
|
/*new_paired_status=*/true, kBleAddress);
|
||||||
|
SetGattServiceClientConnected(true);
|
||||||
|
RunGattClientInitializedCallback(/*pair_failure=*/absl::nullopt);
|
||||||
|
|
||||||
|
// If we get an error while reading model ID, we shouldn't expect a
|
||||||
|
// retroactive pairable device to be found.
|
||||||
|
RunReadModelIdCallback(
|
||||||
|
/*error_code=*/device::BluetoothGattService::GattErrorCode::kNotSupported,
|
||||||
|
kModelIdBytesNoMetadata);
|
||||||
|
EXPECT_FALSE(retroactive_pair_found_);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace quick_pair
|
} // namespace quick_pair
|
||||||
} // namespace ash
|
} // namespace ash
|
||||||
|
@@ -40,6 +40,7 @@ MockBluetoothDevice::MockBluetoothDevice(MockBluetoothAdapter* adapter,
|
|||||||
ON_CALL(*this, GetNameForDisplay())
|
ON_CALL(*this, GetNameForDisplay())
|
||||||
.WillByDefault(
|
.WillByDefault(
|
||||||
Return(base::UTF8ToUTF16(name_ ? name_.value() : "Unnamed Device")));
|
Return(base::UTF8ToUTF16(name_ ? name_.value() : "Unnamed Device")));
|
||||||
|
ON_CALL(*this, GetType()).WillByDefault(ReturnPointee(&transport_));
|
||||||
ON_CALL(*this, GetDeviceType())
|
ON_CALL(*this, GetDeviceType())
|
||||||
.WillByDefault(Return(BluetoothDeviceType::UNKNOWN));
|
.WillByDefault(Return(BluetoothDeviceType::UNKNOWN));
|
||||||
ON_CALL(*this, IsPaired()).WillByDefault(ReturnPointee(&paired_));
|
ON_CALL(*this, IsPaired()).WillByDefault(ReturnPointee(&paired_));
|
||||||
|
@@ -155,6 +155,8 @@ class MockBluetoothDevice : public BluetoothDevice {
|
|||||||
|
|
||||||
void SetPaired(bool paired) { paired_ = paired; }
|
void SetPaired(bool paired) { paired_ = paired; }
|
||||||
|
|
||||||
|
void SetType(device::BluetoothTransport transport) { transport_ = transport; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t bluetooth_class_;
|
uint32_t bluetooth_class_;
|
||||||
absl::optional<std::string> name_;
|
absl::optional<std::string> name_;
|
||||||
@@ -162,6 +164,8 @@ class MockBluetoothDevice : public BluetoothDevice {
|
|||||||
BluetoothDevice::UUIDSet uuids_;
|
BluetoothDevice::UUIDSet uuids_;
|
||||||
bool connected_;
|
bool connected_;
|
||||||
bool paired_;
|
bool paired_;
|
||||||
|
device::BluetoothTransport transport_ =
|
||||||
|
device::BluetoothTransport::BLUETOOTH_TRANSPORT_INVALID;
|
||||||
|
|
||||||
// Used by tests to save callbacks that will be run in the future.
|
// Used by tests to save callbacks that will be run in the future.
|
||||||
base::queue<base::OnceClosure> pending_callbacks_;
|
base::queue<base::OnceClosure> pending_callbacks_;
|
||||||
|
Reference in New Issue
Block a user