Add UX for Retroactive Pairing

PiperOrigin-RevId: 552944003
This commit is contained in:
Qin Wang
2023-08-01 15:38:15 -07:00
committed by Copybara-Service
parent 498fc35aa5
commit 33b2748a8c
14 changed files with 129 additions and 99 deletions
+7
View File
@@ -105,6 +105,12 @@ class FastPairDevice {
return should_show_ui_notification_;
}
void StartedPairing(bool started_pairing) {
has_started_pairing_ = started_pairing;
}
bool HasStartedPairing() const { return has_started_pairing_; }
private:
std::string model_id_;
@@ -135,6 +141,7 @@ class FastPairDevice {
std::optional<DeviceMetadata> metadata_;
std::optional<bool> should_show_ui_notification_;
bool has_started_pairing_ = false;
};
std::ostream& operator<<(std::ostream& stream, const FastPairDevice& device);
@@ -82,6 +82,7 @@ absl::Status FastPairSeekerImpl::StartInitialPairing(
pairing_callback_ = std::make_unique<PairingCallback>(std::move(callback));
device_under_pairing_ = &const_cast<FastPairDevice&>(device);
device_under_pairing_->StartedPairing(true);
pairer_broker_->PairDevice(*device_under_pairing_);
return absl::OkStatus();
}
@@ -100,6 +101,7 @@ absl::Status FastPairSeekerImpl::StartRetroactivePairing(
}
device_under_pairing_ = &const_cast<FastPairDevice&>(device);
device_under_pairing_->StartedPairing(true);
controller_ = std::make_unique<FastPairController>(
&mediums_, device_under_pairing_, executor_);
retroactive_pair_ = std::make_unique<Retroactive>(controller_.get());
+34 -32
View File
@@ -233,42 +233,44 @@ void PairerBrokerImpl::OnFastPairDevicePaired(FastPairDevice& device) {
void PairerBrokerImpl::OnFastPairPairingFailure(FastPairDevice& device,
PairFailure failure) {
MutexLock lock(&mutex_);
++pair_failure_counts_[device.GetModelId()];
NEARBY_LOGS(INFO) << __func__ << ": Device=" << device
<< ", Failure=" << failure << ", Failure Count = "
<< pair_failure_counts_[device.GetModelId()];
if (pair_failure_counts_[device.GetModelId()] == kMaxFailureRetryCount) {
if (!fast_pair_pairers_[device.GetModelId()]->IsPaired()) {
fast_pair_pairers_[device.GetModelId()]->CancelPairing();
{
MutexLock lock(&mutex_);
++pair_failure_counts_[device.GetModelId()];
NEARBY_LOGS(INFO) << __func__ << ": Device=" << device
<< ", Failure=" << failure << ", Failure Count = "
<< pair_failure_counts_[device.GetModelId()];
if (pair_failure_counts_[device.GetModelId()] == kMaxFailureRetryCount) {
if (!fast_pair_pairers_[device.GetModelId()]->IsPaired()) {
fast_pair_pairers_[device.GetModelId()]->CancelPairing();
}
executor_->Execute("EraseHandshakeAndPairers",
[&]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) {
EraseHandshakeAndPairers(device);
});
NEARBY_LOGS(INFO) << __func__
<< ": Reached max failure count. Notifying observers.";
for (auto& observer : observers_.GetObservers()) {
observer->OnPairFailure(device, failure);
}
return;
}
executor_->Execute("EraseHandshakeAndPairers",
[&]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) {
EraseHandshakeAndPairers(device);
});
NEARBY_LOGS(INFO) << __func__
<< ": Reached max failure count. Notifying observers.";
for (auto& observer : observers_.GetObservers()) {
observer->OnPairFailure(device, failure);
}
return;
}
if (!fast_pair_pairers_[device.GetModelId()]->IsPaired()) {
NEARBY_LOGS(INFO) << __func__
<< ": Cancelling pairing and scheduling retry "
"for failed pair attempt.";
fast_pair_pairers_[device.GetModelId()]->CancelPairing();
if (!fast_pair_pairers_[device.GetModelId()]->IsPaired()) {
NEARBY_LOGS(INFO) << __func__
<< ": Cancelling pairing and scheduling retry "
"for failed pair attempt.";
fast_pair_pairers_[device.GetModelId()]->CancelPairing();
fast_pair_pairers_.erase(device.GetModelId());
// Create a timer to wait |kCancelPairingRetryDelay| after cancelling
// pairing to retry the pairing attempt.
cancel_pairing_timer_ = std::make_unique<TimerImpl>();
cancel_pairing_timer_->Start(
kCancelPairingRetryDelay / absl::Milliseconds(1), 0,
[&]() { PairFastPairDevice(device); });
return;
}
fast_pair_pairers_.erase(device.GetModelId());
// Create a timer to wait |kCancelPairingRetryDelay| after cancelling
// pairing to retry the pairing attempt.
cancel_pairing_timer_ = std::make_unique<TimerImpl>();
cancel_pairing_timer_->Start(
kCancelPairingRetryDelay / absl::Milliseconds(1), 0,
[&]() { PairFastPairDevice(device); });
return;
}
fast_pair_pairers_.erase(device.GetModelId());
PairFastPairDevice(device);
}
+36 -17
View File
@@ -27,16 +27,28 @@ void WindowsAdminPlugin::PluginState::DiscoveryClicked(DiscoveryAction action) {
NEARBY_LOGS(INFO) << __func__ << ": Action = kPairToDevice";
absl::Status status = fast_pair_service->GetSeeker()->StartInitialPairing(
*device, InitialPairingParam{},
{.on_pairing_result = [this](const FastPairDevice& device,
absl::Status status) {
NEARBY_LOGS(INFO) << "Pairing result: " << status;
{.on_pairing_result = [this](const FastPairDevice& callback_device,
absl::Status status) {
NEARBY_LOGS(INFO) << "Show pairing result: " << status;
for (auto* observer : observers.GetObservers()) {
observer->OnPairingResult(device.GetMetadata().value(),
status.ok());
observer->OnPairingResult(
const_cast<FastPairDevice&>(callback_device), status.ok());
}
}});
NEARBY_LOGS(INFO) << "StartInitialPairing: " << status;
} break;
case DiscoveryAction::kSaveDeviceToAccount: {
NEARBY_LOGS(INFO) << __func__ << ": Action = kSaveDeviceToAccount";
absl::Status status =
fast_pair_service->GetSeeker()->FinishRetroactivePairing(
*device, FinishRetroactivePairingParam{.save_account_key = true},
{.on_pairing_result = [](const FastPairDevice& device,
absl::Status status) {
NEARBY_LOGS(INFO) << "Finish retro result: " << status;
}});
foreground_currently_showing_notification = false;
NEARBY_LOGS(INFO) << "FinishRetroactivePairing: " << status;
} break;
case DiscoveryAction::kDismissedByOs:
NEARBY_LOGS(INFO) << __func__ << ": Action = kDismissedByOs";
break;
@@ -80,32 +92,39 @@ void WindowsAdminPlugin::OnInitialDiscoveryEvent(
<< "Ignoring initial discovery event because metadata is missing";
return;
}
if (device_->ShouldShowUiNotification().has_value() &&
!device_->ShouldShowUiNotification().value()) {
NEARBY_LOGS(INFO) << __func__ << ": Ignoring because show UI flag is false";
return;
}
if (state_->foreground_currently_showing_notification) {
NEARBY_LOGS(VERBOSE) << __func__
<< ": Already showing a notification for a device";
return;
}
// Show discovery notification
state_->foreground_currently_showing_notification = true;
state_->device = device_;
for (auto* observer : state_->observers.GetObservers()) {
observer->OnUpdateDevice(*metadata);
}
NotifyShowNotification(*device_);
}
void WindowsAdminPlugin::OnPairEvent(const PairEvent& event) {
NEARBY_LOGS(INFO) << "Received on pair event";
absl::Status status = seeker_->StartRetroactivePairing(
*device_, RetroactivePairingParam{},
{.on_pairing_result = [](const FastPairDevice& device,
absl::Status status) {
NEARBY_LOGS(INFO) << "Pairing result: " << status;
// TODO(jsobczak): Ask for user consent and save the Account Key to
// user's account.
{.on_pairing_result = [this](const FastPairDevice& device,
absl::Status status) {
NEARBY_LOGS(INFO) << "Retroactive Pairing result: " << status;
if (!status.ok()) return;
NotifyShowNotification(device);
}});
NEARBY_LOGS(INFO) << "StartRetroactivePairing: " << status;
}
void WindowsAdminPlugin::NotifyShowNotification(const FastPairDevice& device) {
NEARBY_LOGS(INFO) << __func__;
state_->foreground_currently_showing_notification = true;
state_->device = &device;
for (auto* observer : state_->observers.GetObservers()) {
observer->OnUpdateDevice(const_cast<FastPairDevice&>(device));
}
}
} // namespace fastpair
} // namespace nearby
+1
View File
@@ -60,6 +60,7 @@ class WindowsAdminPlugin : public FastPairPlugin {
void OnPairEvent(const PairEvent& event) override;
private:
void NotifyShowNotification(const FastPairDevice& device);
FastPairSeeker* seeker_;
const FastPairDevice* device_;
PluginState* state_;
@@ -70,9 +70,11 @@ void RetroactivePairingDetectorImpl::DevicePairedChanged(
std::optional<FastPairDevice*> existing_device =
repository_->FindDevice(device.GetMacAddress());
if (existing_device.has_value()) {
if (existing_device.has_value() &&
existing_device.value()->HasStartedPairing()) {
// Both classic paired and Fast paired devices call this function, so we
// have to filter out pairing events for devices that we already know.
// have to filter out pairing events for device that paired from Fast Pair.
NEARBY_LOGS(INFO) << __func__ << ": Ignoring Fast paired devices.";
return;
}
+6 -5
View File
@@ -21,11 +21,12 @@ namespace fastpair {
enum class DiscoveryAction {
kUnknown = 0,
kPairToDevice = 1,
kDismissedByUser = 2,
kDismissedByOs = 3,
kLearnMore = 4,
kDone = 5,
kDismissedByTimeout = 6,
kSaveDeviceToAccount = 2,
kDismissedByUser = 3,
kDismissedByOs = 4,
kLearnMore = 5,
kDone = 6,
kDismissedByTimeout = 7,
};
} // namespace fastpair
@@ -21,6 +21,7 @@
#include <vector>
#include "fastpair/common/device_metadata.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/mutex_lock.h"
@@ -37,24 +38,24 @@ class FakeFastPairNotificationControllerObserver
on_pairing_result_latch_ = on_pairing_result_latch;
}
void OnUpdateDevice(const DeviceMetadata& device) override {
void OnUpdateDevice(FastPairDevice& device) override {
MutexLock lock(&mutex_);
device_ = &const_cast<DeviceMetadata&>(device);
device_ = &const_cast<FastPairDevice&>(device);
if (on_device_updated_latch_) {
on_device_updated_latch_->CountDown();
}
}
void OnPairingResult(const DeviceMetadata& device, bool success) override {
void OnPairingResult(FastPairDevice& device, bool success) override {
MutexLock lock(&mutex_);
pairing_result_ = success;
device_ = &const_cast<DeviceMetadata&>(device);
device_ = &const_cast<FastPairDevice&>(device);
if (on_pairing_result_latch_) {
on_pairing_result_latch_->CountDown();
}
}
DeviceMetadata* GetDevice() {
FastPairDevice* GetDevice() {
MutexLock lock(&mutex_);
return device_;
}
@@ -68,7 +69,7 @@ class FakeFastPairNotificationControllerObserver
Mutex mutex_;
CountDownLatch* on_device_updated_latch_;
CountDownLatch* on_pairing_result_latch_;
DeviceMetadata* device_ ABSL_GUARDED_BY(mutex_) = nullptr;
FastPairDevice* device_ ABSL_GUARDED_BY(mutex_) = nullptr;
std::optional<bool> pairing_result_ ABSL_GUARDED_BY(mutex_);
};
} // namespace fastpair
@@ -17,7 +17,7 @@
#include <utility>
#include "absl/functional/any_invocable.h"
#include "fastpair/common/device_metadata.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/ui/actions.h"
#include "internal/platform/logging.h"
@@ -32,7 +32,7 @@ void FastPairNotificationController::RemoveObserver(Observer* observer) {
}
void FastPairNotificationController::NotifyShowDiscovery(
const DeviceMetadata& device) {
FastPairDevice& device) {
NEARBY_LOGS(INFO) << __func__;
for (Observer* observer : observers_.GetObservers()) {
observer->OnUpdateDevice(device);
@@ -40,7 +40,7 @@ void FastPairNotificationController::NotifyShowDiscovery(
}
void FastPairNotificationController::NotifyShowPairingResult(
const DeviceMetadata& device, bool success) {
FastPairDevice& device, bool success) {
NEARBY_LOGS(INFO) << __func__;
for (Observer* observer : observers_.GetObservers()) {
observer->OnPairingResult(device, success);
@@ -48,14 +48,14 @@ void FastPairNotificationController::NotifyShowPairingResult(
}
void FastPairNotificationController::ShowGuestDiscoveryNotification(
const DeviceMetadata& device, DiscoveryCallback callback) {
FastPairDevice& device, DiscoveryCallback callback) {
callback_ = std::move(callback);
NEARBY_LOGS(INFO) << __func__ << "Notify show guest discovery notification. ";
NotifyShowDiscovery(device);
}
void FastPairNotificationController::ShowPairingResultNotification(
const DeviceMetadata& device, bool success) {
FastPairDevice& device, bool success) {
NEARBY_LOGS(INFO) << __func__ << "Notify show pairing result notification. ";
NotifyShowPairingResult(device, success);
}
@@ -16,8 +16,8 @@
#define THIRD_PARTY_NEARBY_FASTPAIR_UI_FAST_PAIR_FAST_PAIR_NOTIFICATION_CONTROLLER_H_
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "fastpair/common/device_metadata.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/ui/actions.h"
#include "internal/base/observer_list.h"
@@ -38,9 +38,8 @@ class FastPairNotificationController {
class Observer {
public:
virtual ~Observer() = default;
virtual void OnUpdateDevice(const DeviceMetadata& device) = 0;
virtual void OnPairingResult(const DeviceMetadata& device,
bool success) = 0;
virtual void OnUpdateDevice(FastPairDevice& device) = 0;
virtual void OnPairingResult(FastPairDevice& device, bool success) = 0;
};
FastPairNotificationController() = default;
@@ -53,15 +52,14 @@ class FastPairNotificationController {
// Observer process
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
void NotifyShowDiscovery(const DeviceMetadata& device);
void NotifyShowPairingResult(const DeviceMetadata& device, bool success);
void NotifyShowDiscovery(FastPairDevice& device);
void NotifyShowPairingResult(FastPairDevice& device, bool success);
// Creates and displays corresponding notification.
void ShowGuestDiscoveryNotification(const DeviceMetadata& device_metadata,
void ShowGuestDiscoveryNotification(FastPairDevice& device,
DiscoveryCallback callback);
void ShowPairingResultNotification(const DeviceMetadata& device_metadata,
bool success);
void ShowPairingResultNotification(FastPairDevice& device, bool success);
// Triggers callback when the related action is clicked.
void OnDiscoveryClicked(DiscoveryAction action);
@@ -14,13 +14,8 @@
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "fastpair/common/device_metadata.h"
#include "fastpair/ui/actions.h"
@@ -32,14 +27,18 @@ namespace fastpair {
namespace {
const int64_t kDeviceId = 10148625;
const char kModelId[] = "9adb11";
const char kDeviceName[] = "Pixel Buds Pro";
constexpr absl::string_view kModelId("9adb11");
constexpr absl::string_view kBleAddress("AA:BB:CC:DD:EE:00");
TEST(FastPairNotificationControllerTest, ShowGuestDiscoveryNotification) {
FastPairNotificationController notification_controller;
proto::GetObservedDeviceResponse response;
DeviceMetadata device_metadata(response);
FastPairDevice device(kModelId, kBleAddress,
Protocol::kFastPairInitialPairing);
device.SetMetadata(device_metadata);
CountDownLatch on_update_device_latch(1);
CountDownLatch on_click_latch(1);
FakeFastPairNotificationControllerObserver observer(&on_update_device_latch,
@@ -48,12 +47,12 @@ TEST(FastPairNotificationControllerTest, ShowGuestDiscoveryNotification) {
EXPECT_EQ(observer.GetDevice(), nullptr);
DiscoveryAction discovery_action = DiscoveryAction::kUnknown;
notification_controller.ShowGuestDiscoveryNotification(
device_metadata, [&](DiscoveryAction action) {
device, [&](DiscoveryAction action) {
on_click_latch.CountDown();
discovery_action = action;
});
on_update_device_latch.Await();
EXPECT_EQ(observer.GetDevice(), &device_metadata);
EXPECT_EQ(observer.GetDevice(), &device);
notification_controller.OnDiscoveryClicked(DiscoveryAction::kPairToDevice);
on_click_latch.Await();
EXPECT_EQ(discovery_action, DiscoveryAction::kPairToDevice);
@@ -63,6 +62,9 @@ TEST(FastPairNotificationControllerTest, ShowPairingResultNotification) {
FastPairNotificationController notification_controller;
proto::GetObservedDeviceResponse response;
DeviceMetadata device_metadata(response);
FastPairDevice device(kModelId, kBleAddress,
Protocol::kFastPairInitialPairing);
device.SetMetadata(device_metadata);
CountDownLatch on_pairing_result_latch(1);
FakeFastPairNotificationControllerObserver observer(nullptr,
@@ -70,9 +72,9 @@ TEST(FastPairNotificationControllerTest, ShowPairingResultNotification) {
notification_controller.AddObserver(&observer);
EXPECT_FALSE(observer.GetPairingResult().has_value());
EXPECT_EQ(observer.GetDevice(), nullptr);
notification_controller.ShowPairingResultNotification(device_metadata, true);
notification_controller.ShowPairingResultNotification(device, true);
on_pairing_result_latch.Await();
EXPECT_EQ(observer.GetDevice(), &device_metadata);
EXPECT_EQ(observer.GetDevice(), &device);
EXPECT_TRUE(observer.GetPairingResult().has_value());
EXPECT_TRUE(observer.GetPairingResult().value());
}
@@ -15,14 +15,10 @@
#include "fastpair/ui/fast_pair/fast_pair_presenter_impl.h"
#include <memory>
#include <optional>
#include <utility>
#include "fastpair/common/device_metadata.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/repository/fast_pair_repository.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace fastpair {
@@ -51,15 +47,14 @@ void FastPairPresenterImpl::ShowDiscovery(
FastPairDevice& device,
FastPairNotificationController& notification_controller,
DiscoveryCallback callback) {
notification_controller.ShowGuestDiscoveryNotification(*device.GetMetadata(),
notification_controller.ShowGuestDiscoveryNotification(device,
std::move(callback));
}
void FastPairPresenterImpl::ShowPairingResult(
FastPairDevice& device,
FastPairNotificationController& notification_controller, bool success) {
notification_controller.ShowPairingResultNotification(*device.GetMetadata(),
success);
notification_controller.ShowPairingResultNotification(device, success);
}
} // namespace fastpair
} // namespace nearby
@@ -72,9 +72,9 @@ TEST(FastPairPresenterImplTest, ShowDiscovery) {
discovery_action = action;
});
on_update_device_latch.Await();
EXPECT_EQ(observer.GetDevice()->GetFastPairVersion(),
EXPECT_EQ(observer.GetDevice()->GetMetadata()->GetFastPairVersion(),
DeviceFastPairVersion::kV1);
EXPECT_THAT(observer.GetDevice()->GetResponse(),
EXPECT_THAT(observer.GetDevice()->GetMetadata()->GetResponse(),
MatchesProto(response_proto));
}
@@ -101,9 +101,9 @@ TEST(FastPairPresenterImplTest, ShowPairingResult) {
fast_pair_presenter.ShowPairingResult(fast_pair_device,
notification_controller, true);
on_pairing_result_latch.Await();
EXPECT_EQ(observer.GetDevice()->GetFastPairVersion(),
EXPECT_EQ(observer.GetDevice()->GetMetadata()->GetFastPairVersion(),
DeviceFastPairVersion::kV1);
EXPECT_THAT(observer.GetDevice()->GetResponse(),
EXPECT_THAT(observer.GetDevice()->GetMetadata()->GetResponse(),
MatchesProto(response_proto));
EXPECT_TRUE(observer.GetPairingResult().has_value());
EXPECT_TRUE(observer.GetPairingResult().value());
@@ -26,12 +26,12 @@ class MockFastPairNotificationController
: public FastPairNotificationController {
public:
MOCK_METHOD(void, ShowGuestDiscoveryNotification,
(const DeviceMetadata&, DiscoveryCallback));
(FastPairDevice & device, DiscoveryCallback));
MOCK_METHOD(void, OnDiscoveryClicked, (DiscoveryAction));
MOCK_METHOD(void, AddObserver, (Observer*));
MOCK_METHOD(void, RemoveObserver, (Observer*));
void NotifyShowDiscovery(const DeviceMetadata& device) {
void NotifyShowDiscovery(FastPairDevice& device) {
for (Observer* observer : observers_.GetObservers()) {
observer->OnUpdateDevice(device);
}