mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 07:36:10 -04:00
Get/Write/Delete account associated device from/to footprints
PiperOrigin-RevId: 546342820
This commit is contained in:
committed by
Copybara-Service
parent
ca9bbd3a9c
commit
5bab62fbb1
@@ -14,6 +14,7 @@ cc_library(
|
||||
visibility = ["//fastpair:__subpackages__"],
|
||||
deps = [
|
||||
"//fastpair/common",
|
||||
"//fastpair/proto:fastpair_cc_proto",
|
||||
"//internal/base:bluetooth_address",
|
||||
"//internal/crypto",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
@@ -40,13 +41,11 @@ cc_library(
|
||||
"//fastpair/proto:fastpair_cc_proto",
|
||||
"//fastpair/proto:proto_builder",
|
||||
"//fastpair/server_access",
|
||||
"//internal/base:bluetooth_address",
|
||||
"//internal/crypto",
|
||||
"//internal/base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/time",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -146,14 +145,15 @@ cc_test(
|
||||
"-Ithird_party",
|
||||
],
|
||||
deps = [
|
||||
":repository",
|
||||
":repository_impl",
|
||||
":test_support",
|
||||
"//fastpair/common",
|
||||
"//fastpair/proto:fastpair_cc_proto",
|
||||
"//fastpair/proto:proto_builder",
|
||||
"//fastpair/server_access:test_support",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -38,10 +38,24 @@ class FakeFastPairRepository : public FastPairRepository {
|
||||
|
||||
void SetFakeMetadata(absl::string_view hex_model_id, proto::Device metadata);
|
||||
void ClearFakeMetadata(absl::string_view hex_model_id);
|
||||
|
||||
// FastPairRepository::
|
||||
void AddObserver(Observer* observer) override{};
|
||||
void RemoveObserver(Observer* observer) override{};
|
||||
|
||||
void GetDeviceMetadata(absl::string_view hex_model_id,
|
||||
DeviceMetadataCallback callback) override;
|
||||
|
||||
void GetUserSavedDevices() override{};
|
||||
|
||||
void WriteAccountAssociationToFootprints(
|
||||
FastPairDevice& device,
|
||||
OperationToFootprintsCallback callback) override{};
|
||||
|
||||
void DeleteAssociatedDeviceByAccountKey(
|
||||
const AccountKey& account_key,
|
||||
OperationToFootprintsCallback callback) override{};
|
||||
|
||||
private:
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<DeviceMetadata>> data_;
|
||||
SingleThreadExecutor executor_;
|
||||
|
||||
@@ -18,19 +18,34 @@
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "fastpair/common/account_key.h"
|
||||
#include "fastpair/common/device_metadata.h"
|
||||
#include "fastpair/common/fast_pair_device.h"
|
||||
#include "fastpair/proto/data.proto.h"
|
||||
#include "fastpair/proto/enum.proto.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
using DeviceMetadataCallback =
|
||||
absl::AnyInvocable<void(std::optional<DeviceMetadata> device_metadata)>;
|
||||
using OperationToFootprintsCallback =
|
||||
absl::AnyInvocable<void(absl::Status status)>;
|
||||
|
||||
class FastPairRepository {
|
||||
public:
|
||||
class Observer {
|
||||
public:
|
||||
virtual ~Observer() = default;
|
||||
|
||||
virtual void OnGetUserSavedDevices(
|
||||
const proto::OptInStatus& opt_in_status,
|
||||
const std::vector<proto::FastPairDevice>& devices) = 0;
|
||||
};
|
||||
|
||||
static FastPairRepository* Get();
|
||||
|
||||
// Computes and returns the SHA256 of the concatenation of the given
|
||||
@@ -40,9 +55,26 @@ class FastPairRepository {
|
||||
|
||||
FastPairRepository();
|
||||
virtual ~FastPairRepository();
|
||||
|
||||
virtual void AddObserver(Observer* observer) = 0;
|
||||
virtual void RemoveObserver(Observer* observer) = 0;
|
||||
|
||||
virtual void GetDeviceMetadata(absl::string_view hex_model_id,
|
||||
DeviceMetadataCallback callback) = 0;
|
||||
|
||||
// Gets a list of devices saved to the current user's account and the user's
|
||||
// opt in status for saving future devices to their account.
|
||||
virtual void GetUserSavedDevices() = 0;
|
||||
|
||||
// Stores the given |account_key| for a |device| on the Footprints server.
|
||||
virtual void WriteAccountAssociationToFootprints(
|
||||
FastPairDevice& device, OperationToFootprintsCallback callback) = 0;
|
||||
|
||||
// Deletes the associated data for a given |account_key|.
|
||||
virtual void DeleteAssociatedDeviceByAccountKey(
|
||||
const AccountKey& account_key,
|
||||
OperationToFootprintsCallback callback) = 0;
|
||||
|
||||
protected:
|
||||
static void SetInstance(FastPairRepository* instance);
|
||||
};
|
||||
|
||||
@@ -18,18 +18,57 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "fastpair/common/device_metadata.h"
|
||||
#include "fastpair/proto/data.proto.h"
|
||||
#include "fastpair/proto/enum.proto.h"
|
||||
#include "fastpair/proto/proto_builder.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
namespace {
|
||||
// This forget pattern is defined in the Android codebase as FORGET_PREFIX_BYTE
|
||||
// and FORGET_PREFIX_LENGTH_IN_BYTES. Currently, those values evaluate to the
|
||||
// string of bytes defined below, which is used as the prefix for the sha256
|
||||
// field of the device.
|
||||
constexpr absl::string_view kForgetPattern = "\xf0\xf0\xf0\xf0";
|
||||
|
||||
// For all intents and purposes, a device that has the "Forget pattern" is no
|
||||
// longer associated to the user's account, and should be treated as removed.
|
||||
bool DoesDeviceHaveForgetPattern(const proto::FastPairDevice& device) {
|
||||
// The device info is modified to have no account key upon removal from
|
||||
// Fast Pair Saved Devices
|
||||
if (device.account_key().empty() ||
|
||||
device.sha256_account_key_public_address().empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// To match Android behavior, we check if the SHA256 of a device begins with
|
||||
// the Forget pattern, defined in Android Fast Pair code. When a device is
|
||||
// forgotten from Android Bluetooth Settings, the SHA256 hash is modified to
|
||||
// contain this pattern.
|
||||
return (device.sha256_account_key_public_address().compare(
|
||||
0, kForgetPattern.length(), kForgetPattern) == 0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
FastPairRepositoryImpl::FastPairRepositoryImpl(FastPairClient* fast_pair_client)
|
||||
: fast_pair_client_(fast_pair_client) {}
|
||||
|
||||
void FastPairRepositoryImpl::AddObserver(Observer* observer) {
|
||||
observers_.AddObserver(observer);
|
||||
}
|
||||
|
||||
void FastPairRepositoryImpl::RemoveObserver(Observer* observer) {
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
void FastPairRepositoryImpl::GetDeviceMetadata(
|
||||
absl::string_view hex_model_id, DeviceMetadataCallback callback) {
|
||||
NEARBY_LOGS(INFO) << __func__ << " with model id= " << hex_model_id;
|
||||
@@ -58,5 +97,102 @@ void FastPairRepositoryImpl::GetDeviceMetadata(
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairRepositoryImpl::WriteAccountAssociationToFootprints(
|
||||
FastPairDevice& device, OperationToFootprintsCallback callback) {
|
||||
proto::UserWriteDeviceRequest request;
|
||||
auto* fast_pair_info = request.mutable_fast_pair_info();
|
||||
BuildFastPairInfo(fast_pair_info, device);
|
||||
executor_.Execute(
|
||||
"Write associated device", [this, request = std::move(request),
|
||||
callback = std::move(callback)]() mutable {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__
|
||||
<< ": Start to write account associated device to footprints.";
|
||||
absl::StatusOr<proto::UserWriteDeviceResponse> response =
|
||||
fast_pair_client_->UserWriteDevice(request);
|
||||
if (response.ok()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__ << "Got GetWriteDeviceResponse from backend.";
|
||||
std::move(callback)(absl::OkStatus());
|
||||
} else {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< __func__
|
||||
<< "Failed to get GetWriteDeviceResponse from backend.";
|
||||
std::move(callback)(response.status());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairRepositoryImpl::DeleteAssociatedDeviceByAccountKey(
|
||||
const AccountKey& account_key, OperationToFootprintsCallback callback) {
|
||||
std::string hex_string = absl::BytesToHexString(account_key.GetAsBytes());
|
||||
absl::AsciiStrToUpper(&hex_string);
|
||||
executor_.Execute(
|
||||
"Delete associated device",
|
||||
[this, hex_account_key = std::move(hex_string),
|
||||
callback = std::move(callback)]() mutable {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__
|
||||
<< ": Start to delete account associated device from footprints";
|
||||
proto::UserDeleteDeviceRequest request;
|
||||
request.set_hex_account_key(hex_account_key);
|
||||
absl::StatusOr<proto::UserDeleteDeviceResponse> response =
|
||||
fast_pair_client_->UserDeleteDevice(request);
|
||||
if (response.ok()) {
|
||||
if (response->success()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__ << "Successfully deleted associated device.";
|
||||
std::move(callback)(absl::OkStatus());
|
||||
} else {
|
||||
NEARBY_LOGS(WARNING) << __func__ << "Failed to delete device.";
|
||||
std::move(callback)(
|
||||
absl::InternalError("Failed to delete device."));
|
||||
}
|
||||
} else {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< __func__
|
||||
<< "Failed to get UserDeleteDeviceResponse from backend.";
|
||||
std::move(callback)(response.status());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairRepositoryImpl::GetUserSavedDevices() {
|
||||
executor_.Execute("Get associated devices", [this]() mutable {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Start to get all account associated devices.";
|
||||
proto::UserReadDevicesRequest request;
|
||||
absl::StatusOr<proto::UserReadDevicesResponse> response =
|
||||
fast_pair_client_->UserReadDevices(request);
|
||||
if (!response.ok()) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< __func__ << "Failed to get UserReadDevicesResponse from backend.";
|
||||
return;
|
||||
}
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< "Got UserReadDevicesResponse from backend.";
|
||||
proto::OptInStatus opt_in_status =
|
||||
proto::OptInStatus::OPT_IN_STATUS_UNKNOWN;
|
||||
std::vector<proto::FastPairDevice> saved_devices;
|
||||
for (const auto& info : response->fast_pair_info()) {
|
||||
if (info.has_opt_in_status()) {
|
||||
opt_in_status = info.opt_in_status();
|
||||
}
|
||||
// We have to check that the devices in Footprints don't use the
|
||||
// "forget pattern" which Android uses in some cases to mark a device
|
||||
// as removed from the user's account.
|
||||
if (!info.has_device() || DoesDeviceHaveForgetPattern(info.device())) {
|
||||
continue;
|
||||
}
|
||||
saved_devices.push_back(info.device());
|
||||
}
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Got " << saved_devices.size()
|
||||
<< " saved devices.";
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->OnGetUserSavedDevices(opt_in_status, saved_devices);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "fastpair/common/device_metadata.h"
|
||||
#include "fastpair/server_access/fast_pair_client.h"
|
||||
#include "fastpair/repository/fast_pair_repository.h"
|
||||
#include "fastpair/server_access/fast_pair_client.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -35,15 +36,28 @@ class FastPairRepositoryImpl : public FastPairRepository {
|
||||
FastPairRepositoryImpl& operator=(const FastPairRepositoryImpl&) = delete;
|
||||
~FastPairRepositoryImpl() override = default;
|
||||
|
||||
void AddObserver(Observer* observer) override;
|
||||
void RemoveObserver(Observer* observer) override;
|
||||
|
||||
void GetDeviceMetadata(absl::string_view hex_model_id,
|
||||
DeviceMetadataCallback callback) override;
|
||||
|
||||
void GetUserSavedDevices() override;
|
||||
|
||||
void WriteAccountAssociationToFootprints(
|
||||
FastPairDevice& device, OperationToFootprintsCallback callback) override;
|
||||
|
||||
void DeleteAssociatedDeviceByAccountKey(
|
||||
const AccountKey& account_key,
|
||||
OperationToFootprintsCallback callback) override;
|
||||
|
||||
private:
|
||||
// A thread for running blocking tasks.
|
||||
SingleThreadExecutor executor_;
|
||||
FastPairClient* fast_pair_client_;
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<DeviceMetadata>>
|
||||
metadata_cache_;
|
||||
ObserverList<FastPairRepository::Observer> observers_;
|
||||
};
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -16,11 +16,17 @@
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "fastpair/common/device_metadata.h"
|
||||
#include "fastpair/proto/data.proto.h"
|
||||
#include "fastpair/proto/fast_pair_string.proto.h"
|
||||
#include "fastpair/proto/proto_builder.h"
|
||||
#include "fastpair/server_access/fake_fast_pair_client.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
|
||||
@@ -28,8 +34,15 @@ namespace nearby {
|
||||
namespace fastpair {
|
||||
namespace {
|
||||
constexpr absl::string_view kHexModelId = "718C17";
|
||||
constexpr absl::string_view kBleAddress = "11:22:33:44:55:66";
|
||||
constexpr absl::string_view kPublicAddress = "20:64:DE:40:F8:93";
|
||||
constexpr absl::string_view kDisplayName = "Test Device";
|
||||
constexpr absl::string_view kAccountKey = "04b85786180add47fb81a04a8ce6b0de";
|
||||
constexpr absl::string_view kInitialPairingdescription =
|
||||
"InitialPairingdescription";
|
||||
constexpr absl::string_view kExpectedSha256Hash =
|
||||
"6353c0075a35b7d81bb30a6190ab246da4b8c55a6111d387400579133c090ed8";
|
||||
constexpr absl::Duration kWaitTimeout = absl::Milliseconds(200);
|
||||
|
||||
// A gMock matcher to match proto values. Use this matcher like:
|
||||
// request/response proto, expected_proto;
|
||||
@@ -41,6 +54,29 @@ MATCHER_P(
|
||||
return arg.SerializeAsString() == expected_proto.SerializeAsString();
|
||||
}
|
||||
|
||||
class FastPairRepositoryObserver : public FastPairRepository::Observer {
|
||||
public:
|
||||
explicit FastPairRepositoryObserver(CountDownLatch* latch) {
|
||||
latch_ = latch;
|
||||
opt_in_status_ = proto::OptInStatus::OPT_IN_STATUS_UNKNOWN;
|
||||
devices_ = std::vector<proto::FastPairDevice>();
|
||||
}
|
||||
|
||||
void OnGetUserSavedDevices(
|
||||
const proto::OptInStatus& opt_in_status,
|
||||
const std::vector<proto::FastPairDevice>& devices) override {
|
||||
for (const auto& device : devices) {
|
||||
devices_.push_back(device);
|
||||
}
|
||||
opt_in_status_ = opt_in_status;
|
||||
latch_->CountDown();
|
||||
}
|
||||
|
||||
CountDownLatch* latch_ = nullptr;
|
||||
proto::OptInStatus opt_in_status_;
|
||||
std::vector<proto::FastPairDevice> devices_;
|
||||
};
|
||||
|
||||
TEST(FastPairRepositoryImplTest, MetadataDownloadSuccess) {
|
||||
FakeFastPairClient fake_fast_pair_client;
|
||||
auto fast_pair_repository =
|
||||
@@ -71,8 +107,272 @@ TEST(FastPairRepositoryImplTest, MetadataDownloadSuccess) {
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
|
||||
// Verifies proto::GetObservedDeviceRequest is as expected.
|
||||
proto::GetObservedDeviceRequest expected_request =
|
||||
fake_fast_pair_client.get_observer_device_request();
|
||||
EXPECT_EQ(expected_request.device_id(), device_id);
|
||||
EXPECT_EQ(expected_request.mode(),
|
||||
proto::GetObservedDeviceRequest::MODE_RELEASE);
|
||||
}
|
||||
|
||||
TEST(FastPairRepositoryImplTest, FailedToDownloadMetadata) {
|
||||
FakeFastPairClient fake_fast_pair_client;
|
||||
auto fast_pair_repository =
|
||||
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
|
||||
|
||||
fake_fast_pair_client.SetGetObservedDeviceResponse(
|
||||
absl::InternalError("No response"));
|
||||
|
||||
CountDownLatch latch(1);
|
||||
fast_pair_repository->GetDeviceMetadata(
|
||||
kHexModelId, [&](std::optional<DeviceMetadata> device_metadata) {
|
||||
EXPECT_FALSE(device_metadata.has_value());
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
}
|
||||
|
||||
TEST(FastPairRepositoryImplTest, GetUserSavedDevicesSuccess) {
|
||||
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_1(kHexModelId, kBleAddress,
|
||||
Protocol::kFastPairInitialPairing);
|
||||
AccountKey account_key(absl::HexStringToBytes(kAccountKey));
|
||||
device_1.SetAccountKey(account_key);
|
||||
device_1.SetPublicAddress(kPublicAddress);
|
||||
device_1.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_1.SetMetadata(device_metadata_1);
|
||||
auto* fast_pair_info_1 = response_proto.add_fast_pair_info();
|
||||
BuildFastPairInfo(fast_pair_info_1, device_1);
|
||||
// Adds device 2.
|
||||
auto* fast_pair_info_2 = response_proto.add_fast_pair_info();
|
||||
fast_pair_info_2->set_opt_in_status(
|
||||
proto::OptInStatus::OPT_IN_STATUS_OPTED_IN);
|
||||
fake_fast_pair_client.SetUserReadDevicesResponse(response_proto);
|
||||
|
||||
// Adds FastPairRepository observer.
|
||||
CountDownLatch latch(1);
|
||||
FastPairRepositoryObserver observer(&latch);
|
||||
EXPECT_EQ(observer.devices_.size(), 0);
|
||||
EXPECT_EQ(observer.opt_in_status_, proto::OptInStatus::OPT_IN_STATUS_UNKNOWN);
|
||||
fast_pair_repository->AddObserver(&observer);
|
||||
|
||||
// Get user's saved device from footprints.
|
||||
fast_pair_repository->GetUserSavedDevices();
|
||||
latch.Await();
|
||||
|
||||
// Verifies user's saved devices are as expected.
|
||||
EXPECT_EQ(observer.opt_in_status_,
|
||||
proto::OptInStatus::OPT_IN_STATUS_OPTED_IN);
|
||||
EXPECT_EQ(observer.devices_.size(), 1);
|
||||
proto::FastPairDevice saved_device = observer.devices_.front();
|
||||
EXPECT_EQ(saved_device.account_key(), account_key.GetAsBytes());
|
||||
EXPECT_EQ(
|
||||
absl::BytesToHexString(saved_device.sha256_account_key_public_address()),
|
||||
kExpectedSha256Hash);
|
||||
proto::StoredDiscoveryItem stored_discovery_item;
|
||||
EXPECT_TRUE(stored_discovery_item.ParseFromString(
|
||||
saved_device.discovery_item_bytes()));
|
||||
EXPECT_EQ(stored_discovery_item.title(), kDisplayName);
|
||||
proto::FastPairStrings fast_pair_strings =
|
||||
stored_discovery_item.fast_pair_strings();
|
||||
EXPECT_EQ(fast_pair_strings.initial_pairing_description(),
|
||||
kInitialPairingdescription);
|
||||
fast_pair_repository->RemoveObserver(&observer);
|
||||
}
|
||||
|
||||
TEST(FastPairRepositoryImplTest, FailedToGetUserSavedDevices) {
|
||||
FakeFastPairClient fake_fast_pair_client;
|
||||
auto fast_pair_repository =
|
||||
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
|
||||
|
||||
fake_fast_pair_client.SetUserReadDevicesResponse(
|
||||
absl::InternalError("No response"));
|
||||
|
||||
// Adds FastPairRepository observer.
|
||||
CountDownLatch latch(1);
|
||||
FastPairRepositoryObserver observer(&latch);
|
||||
fast_pair_repository->AddObserver(&observer);
|
||||
|
||||
// Get user's saved device from footprints.
|
||||
fast_pair_repository->GetUserSavedDevices();
|
||||
EXPECT_FALSE(latch.Await(kWaitTimeout).result());
|
||||
}
|
||||
|
||||
TEST(FastPairRepositoryImplTest, WriteAccountAssociationToFootprintsSuccess) {
|
||||
FakeFastPairClient fake_fast_pair_client;
|
||||
auto fast_pair_repository =
|
||||
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
|
||||
|
||||
// Sets up proto::UserWriteDeviceResponse.
|
||||
proto::UserWriteDeviceResponse response_proto;
|
||||
fake_fast_pair_client.SetUserWriteDeviceResponse(response_proto);
|
||||
|
||||
// Sets up device info to be saved to footprints.
|
||||
FastPairDevice fast_pair_device(kHexModelId, kBleAddress,
|
||||
Protocol::kFastPairInitialPairing);
|
||||
AccountKey account_key(absl::HexStringToBytes(kAccountKey));
|
||||
fast_pair_device.SetAccountKey(account_key);
|
||||
fast_pair_device.SetPublicAddress(kPublicAddress);
|
||||
fast_pair_device.SetDisplayName(kDisplayName);
|
||||
proto::GetObservedDeviceResponse get_observed_device_response;
|
||||
auto* observed_device_strings =
|
||||
get_observed_device_response.mutable_strings();
|
||||
observed_device_strings->set_initial_pairing_description(
|
||||
kInitialPairingdescription);
|
||||
DeviceMetadata device_metadata(get_observed_device_response);
|
||||
fast_pair_device.SetMetadata(device_metadata);
|
||||
|
||||
CountDownLatch latch(1);
|
||||
fast_pair_repository->WriteAccountAssociationToFootprints(
|
||||
fast_pair_device, [&](absl::Status status) {
|
||||
// Verifies successfully write device to footprints.
|
||||
EXPECT_OK(status);
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
|
||||
// Verifies proto::UserWriteDeviceRequest is as expected.
|
||||
proto::UserWriteDeviceRequest expected_request =
|
||||
fake_fast_pair_client.write_device_request();
|
||||
EXPECT_TRUE(expected_request.has_fast_pair_info());
|
||||
auto fast_proto_info = expected_request.fast_pair_info();
|
||||
EXPECT_TRUE(fast_proto_info.has_device());
|
||||
auto device = fast_proto_info.device();
|
||||
EXPECT_EQ(device.account_key(), account_key.GetAsBytes());
|
||||
EXPECT_EQ(absl::BytesToHexString(device.sha256_account_key_public_address()),
|
||||
kExpectedSha256Hash);
|
||||
proto::StoredDiscoveryItem stored_discovery_item;
|
||||
EXPECT_TRUE(
|
||||
stored_discovery_item.ParseFromString(device.discovery_item_bytes()));
|
||||
EXPECT_EQ(stored_discovery_item.title(), kDisplayName);
|
||||
proto::FastPairStrings fast_pair_strings =
|
||||
stored_discovery_item.fast_pair_strings();
|
||||
EXPECT_EQ(fast_pair_strings.initial_pairing_description(),
|
||||
kInitialPairingdescription);
|
||||
}
|
||||
|
||||
TEST(FastPairRepositoryImplTest, FailedToWriteAccountAssociationToFootprints) {
|
||||
FakeFastPairClient fake_fast_pair_client;
|
||||
auto fast_pair_repository =
|
||||
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
|
||||
|
||||
fake_fast_pair_client.SetUserWriteDeviceResponse(
|
||||
absl::InternalError("No response"));
|
||||
|
||||
// Sets up device info to be saved to footprints.
|
||||
FastPairDevice fast_pair_device(kHexModelId, kBleAddress,
|
||||
Protocol::kFastPairInitialPairing);
|
||||
AccountKey account_key(absl::HexStringToBytes(kAccountKey));
|
||||
fast_pair_device.SetAccountKey(account_key);
|
||||
fast_pair_device.SetPublicAddress(kPublicAddress);
|
||||
fast_pair_device.SetDisplayName(kDisplayName);
|
||||
proto::GetObservedDeviceResponse get_observed_device_response;
|
||||
auto* observed_device_strings =
|
||||
get_observed_device_response.mutable_strings();
|
||||
observed_device_strings->set_initial_pairing_description(
|
||||
kInitialPairingdescription);
|
||||
DeviceMetadata device_metadata(get_observed_device_response);
|
||||
fast_pair_device.SetMetadata(device_metadata);
|
||||
|
||||
CountDownLatch latch(1);
|
||||
fast_pair_repository->WriteAccountAssociationToFootprints(
|
||||
fast_pair_device, [&](absl::Status status) {
|
||||
// Failed to write device to footprints.
|
||||
EXPECT_FALSE(status.ok());
|
||||
EXPECT_EQ(status.message(), "No response");
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
}
|
||||
|
||||
TEST(FastPairRepositoryImplTest, DeleteAssociatedDeviceByAccountKeySuccess) {
|
||||
FakeFastPairClient fake_fast_pair_client;
|
||||
auto fast_pair_repository =
|
||||
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
|
||||
|
||||
// Sets up proto::UserDeleteDeviceResponse
|
||||
proto::UserDeleteDeviceResponse response_proto;
|
||||
response_proto.set_success(true);
|
||||
fake_fast_pair_client.SetUserDeleteDeviceResponse(response_proto);
|
||||
|
||||
// AccountKey of the device that will be removed from the footprint.
|
||||
AccountKey account_key(absl::HexStringToBytes(kAccountKey));
|
||||
|
||||
CountDownLatch latch(1);
|
||||
fast_pair_repository->DeleteAssociatedDeviceByAccountKey(
|
||||
account_key, [&](absl::Status status) {
|
||||
// Verifies successfully delete device from the footprints.
|
||||
EXPECT_OK(status);
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
|
||||
// Verifies proto::UserDeleteDeviceRequest is as expected.
|
||||
proto::UserDeleteDeviceRequest expected_request =
|
||||
fake_fast_pair_client.delete_device_request();
|
||||
std::string hex_account_key = std::string(kAccountKey);
|
||||
absl::AsciiStrToUpper(&hex_account_key);
|
||||
EXPECT_EQ(expected_request.hex_account_key(), hex_account_key);
|
||||
}
|
||||
|
||||
TEST(FastPairRepositoryImplTest, FailedToDeleteAssociatedDeviceWithNoResponse) {
|
||||
FakeFastPairClient fake_fast_pair_client;
|
||||
auto fast_pair_repository =
|
||||
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
|
||||
|
||||
fake_fast_pair_client.SetUserDeleteDeviceResponse(
|
||||
absl::InternalError("No response"));
|
||||
|
||||
// AccountKey of the device that will be removed from the footprint.
|
||||
AccountKey account_key(absl::HexStringToBytes(kAccountKey));
|
||||
|
||||
CountDownLatch latch(1);
|
||||
fast_pair_repository->DeleteAssociatedDeviceByAccountKey(
|
||||
account_key, [&](absl::Status status) {
|
||||
// Failed to delete device from the footprints.
|
||||
EXPECT_FALSE(status.ok());
|
||||
EXPECT_EQ(status.message(), "No response");
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
}
|
||||
|
||||
TEST(FastPairRepositoryImplTest, FailedToDeleteAssociatedDeviceWithError) {
|
||||
FakeFastPairClient fake_fast_pair_client;
|
||||
auto fast_pair_repository =
|
||||
std::make_unique<FastPairRepositoryImpl>(&fake_fast_pair_client);
|
||||
|
||||
// Sets up proto::UserDeleteDeviceResponse
|
||||
proto::UserDeleteDeviceResponse response_proto;
|
||||
response_proto.set_success(false);
|
||||
fake_fast_pair_client.SetUserDeleteDeviceResponse(response_proto);
|
||||
|
||||
// AccountKey of the device that will be removed from the footprint.
|
||||
AccountKey account_key(absl::HexStringToBytes(kAccountKey));
|
||||
|
||||
CountDownLatch latch(1);
|
||||
fast_pair_repository->DeleteAssociatedDeviceByAccountKey(
|
||||
account_key, [&](absl::Status status) {
|
||||
// Failed to delete device from the footprints.
|
||||
EXPECT_FALSE(status.ok());
|
||||
EXPECT_EQ(status.message(), "Failed to delete device.");
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
}
|
||||
} // namespace
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
Reference in New Issue
Block a user