From d516e52204dc9407899b6e37b662ade7cc76e91b Mon Sep 17 00:00:00 2001 From: Janusz Sobczak Date: Thu, 6 Jul 2023 02:16:41 -0700 Subject: [PATCH] Add FastPairService adapter. Add an adapter and windows plugin for scalable seeker, PiperOrigin-RevId: 545920541 --- fastpair/dart/windows/BUILD | 4 + .../dart/windows/fast_pair_service_adapter.cc | 106 +++++++++++++++--- .../dart/windows/fast_pair_service_adapter.h | 8 +- .../windows/fast_pair_service_adapter_dart.cc | 20 ++-- .../windows/fast_pair_service_adapter_dart.h | 12 +- fastpair/fast_pair_events.h | 4 +- fastpair/fast_pair_service.cc | 15 ++- fastpair/internal/fast_pair_seeker_impl.cc | 6 +- fastpair/plugins/BUILD | 17 +++ fastpair/plugins/windows_admin_plugin.cc | 71 ++++++++++++ fastpair/plugins/windows_admin_plugin.h | 69 ++++++++++++ 11 files changed, 290 insertions(+), 42 deletions(-) create mode 100644 fastpair/plugins/windows_admin_plugin.cc create mode 100644 fastpair/plugins/windows_admin_plugin.h diff --git a/fastpair/dart/windows/BUILD b/fastpair/dart/windows/BUILD index d6caa612..fcdebdd8 100644 --- a/fastpair/dart/windows/BUILD +++ b/fastpair/dart/windows/BUILD @@ -35,8 +35,10 @@ lexan.cc_windows_dll( "//location/nearby/apps/better_together/windows/fast_pair:__subpackages__", ], deps = [ + "//fastpair:fast_pair_service", "//fastpair/dart/proto:fastpair_cc_proto", "//fastpair/keyed_service", + "//fastpair/plugins:windows_admin_plugin", "//fastpair/ui:fast_pair_ui", "//internal/platform:logging", "//internal/platform/implementation/windows", @@ -69,9 +71,11 @@ lexan.cc_windows_dll( "//location/nearby/apps/better_together/windows/fast_pair:__subpackages__", ], deps = [ + "//fastpair:fast_pair_service", "//fastpair/common", "//fastpair/dart/proto:fastpair_cc_proto", "//fastpair/keyed_service", + "//fastpair/plugins:windows_admin_plugin", "//fastpair/ui:fast_pair_ui", "//internal/platform:logging", "//internal/platform/implementation/windows", diff --git a/fastpair/dart/windows/fast_pair_service_adapter.cc b/fastpair/dart/windows/fast_pair_service_adapter.cc index ef7e815e..9122e1e9 100644 --- a/fastpair/dart/windows/fast_pair_service_adapter.cc +++ b/fastpair/dart/windows/fast_pair_service_adapter.cc @@ -17,8 +17,11 @@ #include #include +#include "fastpair/fast_pair_service.h" +#include "fastpair/internal/fast_pair_seeker_impl.h" #include "fastpair/keyed_service/fast_pair_mediator.h" #include "fastpair/keyed_service/fast_pair_mediator_factory.h" +#include "fastpair/plugins/windows_admin_plugin.h" #include "fastpair/ui/actions.h" #include "fastpair/ui/fast_pair/fast_pair_notification_controller.h" #include "internal/platform/logging.h" @@ -27,69 +30,138 @@ namespace nearby { namespace fastpair { namespace windows { -static Mediator *pMediator_ = nullptr; +// Set to 1 to use Mediator. Set to 0 to use scalable seeker. +#define USE_MEDIATOR 0 + +namespace { +#if USE_MEDIATOR +Mediator *pMediator_ = nullptr; +#else +WindowsAdminPlugin::PluginState *plugin_state = nullptr; +#endif /* USE_MEDIATOR */ + +WindowsAdminPlugin::PluginState *InitFastPairService() { + NEARBY_LOGS(INFO) << "[[ Init Fast Pair Service. ]]"; + plugin_state = new WindowsAdminPlugin::PluginState(); + plugin_state->fast_pair_service = std::make_unique(); + plugin_state->fast_pair_service->RegisterPluginProvider( + "admin", std::make_unique(plugin_state)); + return plugin_state; +} + +void CloseFastPairService(void *instance) { + NEARBY_LOGS(INFO) << "[[ Closing Fast Pair Service. ]]"; + CHECK_EQ(plugin_state, instance); + delete plugin_state; + plugin_state = nullptr; + NEARBY_LOGS(INFO) << "[[ Successfully closed Fast Pair Service. ]]"; +} + +void StartFastPairServiceScan(void *instance) { + CHECK_EQ(plugin_state, instance); + FastPairSeekerExt *seeker = static_cast( + plugin_state->fast_pair_service->GetSeeker()); + absl::Status status = seeker->StartFastPairScan(); + NEARBY_LOGS(INFO) << "Start FP scan result: " << status; +} +} // namespace + void *InitMediator() { #if defined(NEARBY_LOG_SEVERITY) // Direct override of logging level. NEARBY_LOG_SET_SEVERITY(NEARBY_LOG_SEVERITY); #endif // LOG_SEVERITY_VERBOSE; - Mediator *pMediator = MediatorFactory::GetInstance()->CreateMediator(); - pMediator_ = pMediator; +#if USE_MEDIATOR + pMediator_ = MediatorFactory::GetInstance()->CreateMediator(); return pMediator_; +#else + return InitFastPairService(); +#endif /* USE_MEDIATOR */ } -void CloseMediator(Mediator *pMediator) { +void CloseMediator(void *instance) { +#if USE_MEDIATOR NEARBY_LOGS(INFO) << "[[ Closing Fast Pair Mediator. ]]"; if (pMediator_ != nullptr) delete pMediator_; NEARBY_LOGS(INFO) << "[[ Successfully closed Fast Pair Mediator. ]]"; +#else + CloseFastPairService(instance); +#endif /* USE_MEDIATOR */ } -void __stdcall StartScan(Mediator *pMediator) { +void __stdcall StartScan(void *instance) { NEARBY_LOGS(INFO) << "StartScan is called"; +#if USE_MEDIATOR if (pMediator_ == nullptr) { NEARBY_LOGS(VERBOSE) << "The pMediator is a null pointer."; return; } - pMediator_->StartScanning(); + Mediator *mediator = static_cast(instance); + mediator->StartScanning(); +#else + StartFastPairServiceScan(instance); +#endif /* USE_MEDIATOR */ } void __stdcall AddNotificationControllerObserver( - Mediator *pMediator, FastPairNotificationController::Observer *observer) { + void *instance, FastPairNotificationController::Observer *observer) { NEARBY_LOGS(INFO) << "AddNotificationControllerObserver is called"; +#if USE_MEDIATOR if (pMediator_ == nullptr) { NEARBY_LOGS(VERBOSE) << "The pMediator is a null pointer."; return; } - static_cast(pMediator)->GetNotificationController()->AddObserver( - observer); + Mediator *mediator = static_cast(instance); + mediator->GetNotificationController()->AddObserver(observer); +#else + CHECK_EQ(plugin_state, instance); + plugin_state->observers.AddObserver(observer); +#endif /* USE_MEDIATOR */ } void __stdcall RemoveNotificationControllerObserver( - Mediator *pMediator, FastPairNotificationController::Observer *observer) { + void *instance, FastPairNotificationController::Observer *observer) { +#if USE_MEDIATOR if (pMediator_ == nullptr) { NEARBY_LOGS(VERBOSE) << "The pMediator is a null pointer."; return; } - static_cast(pMediator) - ->GetNotificationController() - ->RemoveObserver(observer); + Mediator *mediator = static_cast(instance); + mediator->GetNotificationController()->RemoveObserver(observer); +#else + CHECK_EQ(plugin_state, instance); + plugin_state->observers.RemoveObserver(observer); +#endif /* USE_MEDIATOR */ } -void __stdcall DiscoveryClicked(Mediator *pMediator, DiscoveryAction action) { - static_cast(pMediator) - ->GetNotificationController() - ->OnDiscoveryClicked(action); +void __stdcall DiscoveryClicked(void *instance, DiscoveryAction action) { +#if USE_MEDIATOR + Mediator *mediator = static_cast(instance); + mediator->GetNotificationController()->OnDiscoveryClicked(action); +#else + CHECK_EQ(plugin_state, instance); + plugin_state->DiscoveryClicked(action); +#endif /* USE_MEDIATOR */ } void __stdcall SetIsScreenLocked(bool is_locked) { +#if USE_MEDIATOR if (pMediator_ == nullptr) { NEARBY_LOGS(INFO) << "The pMediator is a null pointer."; return; } NEARBY_LOGS(INFO) << "SetIsScreenLocked :" << is_locked; pMediator_->SetIsScreenLocked(is_locked); +#else + if (plugin_state == nullptr) { + NEARBY_LOGS(INFO) << "Plugin not initialized"; + return; + } + plugin_state->SetIsScreenLocked(is_locked); +#endif /* USE_MEDIATOR */ } + } // namespace windows } // namespace fastpair } // namespace nearby diff --git a/fastpair/dart/windows/fast_pair_service_adapter.h b/fastpair/dart/windows/fast_pair_service_adapter.h index 19d6ce4d..cdc2a8f0 100644 --- a/fastpair/dart/windows/fast_pair_service_adapter.h +++ b/fastpair/dart/windows/fast_pair_service_adapter.h @@ -31,18 +31,18 @@ namespace windows { DLL_EXPORT void *__stdcall InitMediator(); // Starts scanning service -DLL_EXPORT void __stdcall StartScan(Mediator *pMediator); +DLL_EXPORT void __stdcall StartScan(void *instance); // Adds a notification controller observer to the service. DLL_EXPORT void __stdcall AddNotificationControllerObserver( - Mediator *pMediator, FastPairNotificationController::Observer *observer); + void *instance, FastPairNotificationController::Observer *observer); // Removes a notification controller observer to the service. DLL_EXPORT void __stdcall RemoveNotificationControllerObserver( - Mediator *pMediator, FastPairNotificationController::Observer *observer); + void *instance, FastPairNotificationController::Observer *observer); // Triggers discovery click action -DLL_EXPORT void DiscoveryClicked(Mediator *pMediator, DiscoveryAction action); +DLL_EXPORT void DiscoveryClicked(void *instance, DiscoveryAction action); // Sends screen locked event. DLL_EXPORT void __stdcall SetIsScreenLocked(bool is_locked); diff --git a/fastpair/dart/windows/fast_pair_service_adapter_dart.cc b/fastpair/dart/windows/fast_pair_service_adapter_dart.cc index 1d6fa4c6..43c22cd8 100644 --- a/fastpair/dart/windows/fast_pair_service_adapter_dart.cc +++ b/fastpair/dart/windows/fast_pair_service_adapter_dart.cc @@ -68,40 +68,38 @@ class NotificationControllerObserver }; } // namespace -void InitMediatorDart() { InitMediator(); } +void *InitMediatorDart() { return InitMediator(); } -void StartScanDart(Mediator *pMediator) { StartScan(pMediator); } +void StartScanDart(void *instance) { StartScan(instance); } static absl::flat_hash_map> *notification_controller_observer_map_ = new absl::flat_hash_map< Dart_Port, std::unique_ptr>(); -void AddNotificationControllerObserverDart(Mediator *pMediator, - Dart_Port port) { +void AddNotificationControllerObserverDart(void *instance, Dart_Port port) { auto observer = std::make_unique(port); - AddNotificationControllerObserver(pMediator, observer.get()); + AddNotificationControllerObserver(instance, observer.get()); notification_controller_observer_map_->insert({port, std::move(observer)}); CHECK(notification_controller_observer_map_->contains(port)); } -void RemoveNotificationControllerObserverDart(Mediator *pMediator, - Dart_Port port) { +void RemoveNotificationControllerObserverDart(void *instance, Dart_Port port) { auto it = notification_controller_observer_map_->find(port); if (it != notification_controller_observer_map_->end()) { - RemoveNotificationControllerObserver(pMediator, it->second.get()); + RemoveNotificationControllerObserver(instance, it->second.get()); notification_controller_observer_map_->erase(it); } } -void DiscoveryClickedDart(Mediator *pMediator, int action) { +void DiscoveryClickedDart(void *instance, int action) { switch (action) { case ::nearby::fastpair::dart::proto::DISCOVERY_ACTION_PAIR_TO_DEVICE: - DiscoveryClicked(pMediator, + DiscoveryClicked(instance, ::nearby::fastpair::DiscoveryAction::kPairToDevice); break; case ::nearby::fastpair::dart::proto::DISCOVERY_ACTION_LEARN_MORE: - DiscoveryClicked(pMediator, + DiscoveryClicked(instance, ::nearby::fastpair::DiscoveryAction::kLearnMore); break; } diff --git a/fastpair/dart/windows/fast_pair_service_adapter_dart.h b/fastpair/dart/windows/fast_pair_service_adapter_dart.h index ab93e94f..b59168ac 100644 --- a/fastpair/dart/windows/fast_pair_service_adapter_dart.h +++ b/fastpair/dart/windows/fast_pair_service_adapter_dart.h @@ -25,21 +25,21 @@ namespace fastpair { namespace windows { // Initiates a default Mediator instance. -DLL_EXPORT void __stdcall InitMediatorDart(); +DLL_EXPORT void* __stdcall InitMediatorDart(); // Starts scanning service -DLL_EXPORT void __stdcall StartScanDart(Mediator* pMediator); +DLL_EXPORT void __stdcall StartScanDart(void* instance); // Adds a notification controller observer to the service. -DLL_EXPORT void __stdcall AddNotificationControllerObserverDart( - Mediator* pMediator, Dart_Port port); +DLL_EXPORT void __stdcall AddNotificationControllerObserverDart(void* instance, + Dart_Port port); // Removes a notification controller observer to the service. DLL_EXPORT void __stdcall RemoveNotificationControllerObserverDart( - Mediator* pMediator, Dart_Port port); + void* instance, Dart_Port port); // Triggers discovery click action -DLL_EXPORT void __stdcall DiscoveryClickedDart(Mediator* pMediator, int action); +DLL_EXPORT void __stdcall DiscoveryClickedDart(void* instance, int action); } // namespace windows } // namespace fastpair diff --git a/fastpair/fast_pair_events.h b/fastpair/fast_pair_events.h index aa8c93a4..93cd727c 100644 --- a/fastpair/fast_pair_events.h +++ b/fastpair/fast_pair_events.h @@ -26,7 +26,9 @@ struct InitialDiscoveryEvent {}; struct SubsequentDiscoveryEvent {}; -struct PairEvent {}; +struct PairEvent { + bool is_paired; +}; struct ScreenEvent { std::optional is_locked; diff --git a/fastpair/fast_pair_service.cc b/fastpair/fast_pair_service.cc index 2d1d9b8e..42275e22 100644 --- a/fastpair/fast_pair_service.cc +++ b/fastpair/fast_pair_service.cc @@ -45,7 +45,7 @@ constexpr FeatureFlags::Flags fast_pair_feature_flags = FeatureFlags::Flags{ .enable_scan_for_fast_pair_advertisement = true, }; constexpr absl::Duration kTimeout = absl::Seconds(3); -} +} // namespace FastPairService::FastPairService() : FastPairService(std::make_unique(), @@ -159,8 +159,19 @@ void FastPairService::OnInitialDiscoveryEvent(const FastPairDevice& device, void FastPairService::OnSubsequentDiscoveryEvent( const FastPairDevice& device, SubsequentDiscoveryEvent event) {} + void FastPairService::OnPairEvent(const FastPairDevice& device, - PairEvent event) {} + PairEvent event) { + executor_.Execute( + "on-pair-event", [this, device = &device, event = std::move(event)]() { + NEARBY_LOGS(INFO) << "OnPairEvent " << *device; + for (auto& entry : plugin_states_) { + auto plugin = entry.second.GetPlugin(seeker_.get(), device); + plugin->OnPairEvent(event); + } + }); +} + void FastPairService::OnScreenEvent(ScreenEvent event) { executor_.Execute("on-screen-event", [this, event = std::move(event)]() { NEARBY_LOGS(INFO) << "OnScreenEvent "; diff --git a/fastpair/internal/fast_pair_seeker_impl.cc b/fastpair/internal/fast_pair_seeker_impl.cc index f719a7ef..0e83b95d 100644 --- a/fastpair/internal/fast_pair_seeker_impl.cc +++ b/fastpair/internal/fast_pair_seeker_impl.cc @@ -221,6 +221,10 @@ void FastPairSeekerImpl::DevicePairedChanged(BluetoothDevice& device, bool new_paired_status) { NEARBY_LOGS(VERBOSE) << __func__ << "(" << device.GetMacAddress() << ", " << new_paired_status << ")"; + // Note, the FP service will be notified about paired events from the + // retroactive pairing path if `device` is an FP device. + // TODO(jsobczak): Notify service about unpair events if `device` is a known + // FP device. } void FastPairSeekerImpl::DeviceConnectedStateChanged(BluetoothDevice& device, @@ -231,7 +235,7 @@ void FastPairSeekerImpl::DeviceConnectedStateChanged(BluetoothDevice& device, void FastPairSeekerImpl::OnRetroactivePairFound(FastPairDevice& device) { NEARBY_LOGS(VERBOSE) << __func__ << ": " << device; - callbacks_.on_pair_event(device, PairEvent{}); + callbacks_.on_pair_event(device, PairEvent{.is_paired = true}); } } // namespace fastpair diff --git a/fastpair/plugins/BUILD b/fastpair/plugins/BUILD index 9c5aadbc..2b88e45f 100644 --- a/fastpair/plugins/BUILD +++ b/fastpair/plugins/BUILD @@ -33,6 +33,23 @@ cc_library( ], ) +cc_library( + name = "windows_admin_plugin", + srcs = ["windows_admin_plugin.cc"], + hdrs = ["windows_admin_plugin.h"], + compatible_with = ["//buildenv/target:non_prod"], + visibility = ["//:__subpackages__"], + deps = [ + "//fastpair:fast_pair_events", + "//fastpair:fast_pair_plugin", + "//fastpair:fast_pair_seeker", + "//fastpair:fast_pair_service", + "//fastpair/common", + "//fastpair/ui:fast_pair_ui", + "//internal/platform:types", + ], +) + cc_test( name = "fake_initial_pair_plugin_test", size = "small", diff --git a/fastpair/plugins/windows_admin_plugin.cc b/fastpair/plugins/windows_admin_plugin.cc new file mode 100644 index 00000000..99430c11 --- /dev/null +++ b/fastpair/plugins/windows_admin_plugin.cc @@ -0,0 +1,71 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastpair/plugins/windows_admin_plugin.h" + +#include "fastpair/internal/fast_pair_seeker_impl.h" + +namespace nearby { +namespace fastpair { + +void WindowsAdminPlugin::PluginState::DiscoveryClicked(DiscoveryAction action) { + NEARBY_LOGS(INFO) << __func__; + if (device == nullptr || fast_pair_service == nullptr) return; + absl::Status status = fast_pair_service->GetSeeker()->StartInitialPairing( + *device, InitialPairingParam{}, + {.on_pairing_result = [](const FastPairDevice& device, + absl::Status status) { + NEARBY_LOGS(INFO) << "Pairing result: " << status; + }}); + NEARBY_LOGS(INFO) << "StartInitialPairing: " << status; +} + +void WindowsAdminPlugin::PluginState::SetIsScreenLocked(bool is_locked) { + NEARBY_LOGS(INFO) << __func__; + if (device == nullptr || fast_pair_service == nullptr) return; + FastPairSeekerExt* seeker = + static_cast(fast_pair_service->GetSeeker()); + seeker->SetIsScreenLocked(is_locked); +} + +void WindowsAdminPlugin::OnInitialDiscoveryEvent( + const InitialDiscoveryEvent& event) { + NEARBY_LOGS(INFO) << "Received on initial discovery event"; + auto metadata = device_->GetMetadata(); + if (!metadata) { + NEARBY_LOGS(INFO) + << "Ignoring initial discovery event because metadata is missing"; + return; + } + state_->device = device_; + for (auto* observer : state_->observers.GetObservers()) { + observer->OnUpdateDevice(*metadata); + } +} + +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 constent and save the Account Key to + // user's account. + }}); + NEARBY_LOGS(INFO) << "StartRetroactivePairing: " << status; +} + +} // namespace fastpair +} // namespace nearby diff --git a/fastpair/plugins/windows_admin_plugin.h b/fastpair/plugins/windows_admin_plugin.h new file mode 100644 index 00000000..5d2ce3d3 --- /dev/null +++ b/fastpair/plugins/windows_admin_plugin.h @@ -0,0 +1,69 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef THIRD_PARTY_NEARBY_FASTPAIR_PLUGINS_WINDOWS_ADMIN_PLUGIN_H_ +#define THIRD_PARTY_NEARBY_FASTPAIR_PLUGINS_WINDOWS_ADMIN_PLUGIN_H_ + +#include + +#include "fastpair/common/fast_pair_device.h" +#include "fastpair/fast_pair_events.h" +#include "fastpair/fast_pair_plugin.h" +#include "fastpair/fast_pair_seeker.h" +#include "fastpair/fast_pair_service.h" +#include "fastpair/ui/actions.h" +#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h" +#include "internal/platform/logging.h" + +namespace nearby { +namespace fastpair { + +class WindowsAdminPlugin : public FastPairPlugin { + public: + struct PluginState { + void DiscoveryClicked(DiscoveryAction action); + void SetIsScreenLocked(bool is_locked); + ObserverList observers; + const FastPairDevice* device = nullptr; + std::unique_ptr fast_pair_service; + }; + class Provider : public FastPairPluginProvider { + public: + explicit Provider(PluginState* state) : state_(state) {} + std::unique_ptr GetPlugin( + FastPairSeeker* seeker, const FastPairDevice* device) override { + return std::make_unique(seeker, device, state_); + } + + private: + PluginState* state_; + }; + + WindowsAdminPlugin(FastPairSeeker* seeker, const FastPairDevice* device, + PluginState* state) + : seeker_(seeker), device_(device), state_(state) {} + + void OnInitialDiscoveryEvent(const InitialDiscoveryEvent& event) override; + void OnPairEvent(const PairEvent& event) override; + + private: + FastPairSeeker* seeker_; + const FastPairDevice* device_; + PluginState* state_; +}; + +} // namespace fastpair +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_FASTPAIR_PLUGINS_WINDOWS_ADMIN_PLUGIN_H_