Checks if a found device is associated with current account

PiperOrigin-RevId: 547549817
This commit is contained in:
Qin Wang
2023-07-12 11:18:34 -07:00
committed by Copybara-Service
parent d559a4a435
commit ffdd25a194
5 changed files with 149 additions and 0 deletions
@@ -56,6 +56,10 @@ class FakeFastPairRepository : public FastPairRepository {
const AccountKey& account_key,
OperationToFootprintsCallback callback) override{};
void CheckIfAssociatedWithCurrentAccount(
AccountKeyFilter& account_key_filter,
CheckAccountKeysCallback callback) override{};
private:
absl::flat_hash_map<std::string, std::unique_ptr<DeviceMetadata>> data_;
SingleThreadExecutor executor_;
@@ -23,6 +23,7 @@
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "fastpair/common/account_key.h"
#include "fastpair/common/account_key_filter.h"
#include "fastpair/common/device_metadata.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/proto/data.proto.h"
@@ -32,6 +33,9 @@ namespace nearby {
namespace fastpair {
using DeviceMetadataCallback =
absl::AnyInvocable<void(std::optional<DeviceMetadata> device_metadata)>;
using CheckAccountKeysCallback =
absl::AnyInvocable<void(std::optional<AccountKey> account_key,
std::optional<absl::string_view> model_id)>;
using OperationToFootprintsCallback =
absl::AnyInvocable<void(absl::Status status)>;
@@ -75,6 +79,12 @@ class FastPairRepository {
const AccountKey& account_key,
OperationToFootprintsCallback callback) = 0;
// Checks all account keys associated with current user's account against the
// given filter. If a match is found, return the account key.
virtual void CheckIfAssociatedWithCurrentAccount(
AccountKeyFilter& account_key_filter,
CheckAccountKeysCallback callback) = 0;
protected:
static void SetInstance(FastPairRepository* instance);
};
@@ -188,11 +188,47 @@ void FastPairRepositoryImpl::GetUserSavedDevices() {
}
NEARBY_LOGS(INFO) << __func__ << ": Got " << saved_devices.size()
<< " saved devices.";
// TODO(b/289139378) : save device's in local cache.
for (auto& observer : observers_.GetObservers()) {
observer->OnGetUserSavedDevices(opt_in_status, saved_devices);
}
});
}
void FastPairRepositoryImpl::CheckIfAssociatedWithCurrentAccount(
AccountKeyFilter& account_key_filter, CheckAccountKeysCallback callback) {
executor_.Execute("Check if associated.", [this,
account_key_filter =
std::move(account_key_filter),
callback = std::move(
callback)]() mutable {
NEARBY_LOGS(INFO) << __func__
<< ": Start to check if associated with current account.";
proto::UserReadDevicesRequest request;
absl::StatusOr<proto::UserReadDevicesResponse> response =
fast_pair_client_->UserReadDevices(request);
if (response.ok()) {
for (const auto& info : response->fast_pair_info()) {
if (!info.has_device()) {
continue;
}
AccountKey account_key(info.device().account_key());
if (!account_key_filter.IsPossiblyInSet(account_key)) {
continue;
}
proto::StoredDiscoveryItem device;
if (device.ParseFromString(info.device().discovery_item_bytes())) {
NEARBY_LOGS(INFO)
<< "Account key matched with a paired device: " << device.title();
std::move(callback)(account_key, device.id());
return;
}
}
}
NEARBY_LOGS(INFO) << "Account key does not match any paired devices.";
std::move(callback)(std::nullopt, std::nullopt);
});
}
} // namespace fastpair
} // namespace nearby
@@ -51,6 +51,10 @@ class FastPairRepositoryImpl : public FastPairRepository {
const AccountKey& account_key,
OperationToFootprintsCallback callback) override;
void CheckIfAssociatedWithCurrentAccount(
AccountKeyFilter& account_key_filter,
CheckAccountKeysCallback callback) override;
private:
// A thread for running blocking tasks.
SingleThreadExecutor executor_;
@@ -373,6 +373,101 @@ TEST(FastPairRepositoryImplTest, FailedToDeleteAssociatedDeviceWithError) {
});
latch.Await();
}
// Test data comes from:
// https://developers.google.com/nearby/fast-pair/specifications/appendix/testcases#test_cases
TEST(FastPairRepositoryImplTest, DeviceAssociatedWithCurrentAccountSuccess) {
const std::vector<uint8_t> filter{0x02, 0x0C, 0x80, 0x2A};
const std::vector<uint8_t> salt{0xC7, 0xC8};
const std::vector<uint8_t> account_key_vec{0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB,
0xCC, 0xDD, 0xEE, 0xFF};
FakeFastPairClient fake_fast_pair_client;
auto fast_pair_repository =
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
// Sets up two devices to proto::UserReadDevicesResponse.
proto::UserReadDevicesResponse response_proto;
// Adds device 1.
auto* fast_pair_info_1 = response_proto.add_fast_pair_info();
fast_pair_info_1->set_opt_in_status(
proto::OptInStatus::OPT_IN_STATUS_OPTED_IN);
// Adds device 2.
FastPairDevice device_2(kHexModelId, kBleAddress,
Protocol::kFastPairInitialPairing);
AccountKey account_key(account_key_vec);
device_2.SetAccountKey(account_key);
device_2.SetPublicAddress(kPublicAddress);
device_2.SetDisplayName(kDisplayName);
proto::GetObservedDeviceResponse get_observed_device_response_1;
auto* observed_device_strings_1 =
get_observed_device_response_1.mutable_strings();
observed_device_strings_1->set_initial_pairing_description(
kInitialPairingdescription);
DeviceMetadata device_metadata_1(get_observed_device_response_1);
device_2.SetMetadata(device_metadata_1);
auto* fast_pair_info_2 = response_proto.add_fast_pair_info();
BuildFastPairInfo(fast_pair_info_2, device_2);
fake_fast_pair_client.SetUserReadDevicesResponse(response_proto);
AccountKeyFilter account_key_filter(filter, salt);
CountDownLatch latch(1);
// Get user's saved device from footprints.
fast_pair_repository->CheckIfAssociatedWithCurrentAccount(
account_key_filter, [&](std::optional<AccountKey> cb_account_key,
std::optional<absl::string_view> cb_model_id) {
ASSERT_TRUE(cb_account_key.has_value());
ASSERT_TRUE(cb_model_id.has_value());
EXPECT_EQ(cb_account_key.value(), account_key);
EXPECT_EQ(cb_model_id.value(), kHexModelId);
latch.CountDown();
});
latch.Await();
}
TEST(FastPairRepositoryImplTest, DeviceNotAssociatedWithCurrentAccount) {
const std::vector<uint8_t> filter{0x02, 0x0C, 0x80, 0x2A};
const std::vector<uint8_t> salt{0xC7, 0xC8};
const std::vector<uint8_t> account_key_vec{0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
0x44, 0x44, 0x55, 0x55, 0x66, 0x66,
0x77, 0x77, 0x88, 0x88};
FakeFastPairClient fake_fast_pair_client;
auto fast_pair_repository =
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
// Sets up two devices to proto::UserReadDevicesResponse.
// Adds device 1.
proto::UserReadDevicesResponse response_proto;
FastPairDevice device(kHexModelId, kBleAddress,
Protocol::kFastPairInitialPairing);
AccountKey account_key(account_key_vec);
device.SetAccountKey(account_key);
device.SetPublicAddress(kPublicAddress);
device.SetDisplayName(kDisplayName);
proto::GetObservedDeviceResponse get_observed_device_response;
DeviceMetadata device_metadata(get_observed_device_response);
device.SetMetadata(device_metadata);
auto* fast_pair_info = response_proto.add_fast_pair_info();
BuildFastPairInfo(fast_pair_info, device);
fake_fast_pair_client.SetUserReadDevicesResponse(response_proto);
AccountKeyFilter account_key_filter(filter, salt);
CountDownLatch latch(1);
// Get user's saved device from footprints.
fast_pair_repository->CheckIfAssociatedWithCurrentAccount(
account_key_filter, [&](std::optional<AccountKey> cb_account_key,
std::optional<absl::string_view> cb_model_id) {
EXPECT_FALSE(cb_account_key.has_value());
EXPECT_FALSE(cb_model_id.has_value());
latch.CountDown();
});
latch.Await();
}
} // namespace
} // namespace fastpair
} // namespace nearby