mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Increase plugin life time
A plugin is created when it is first needed and destroyed when the FP device is destroyed. This allows the plugins to keep state during long running operations such as presenting a UI query. PiperOrigin-RevId: 543502491
This commit is contained in:
committed by
Copybara-Service
parent
c5c65714a0
commit
33abd7d879
@@ -39,11 +39,14 @@ FastPairService::FastPairService()
|
||||
: FastPairService(std::make_unique<FastPairRepositoryImpl>()) {}
|
||||
|
||||
FastPairService::FastPairService(std::unique_ptr<FastPairRepository> repository)
|
||||
: fast_pair_repository_(std::move(repository)) {
|
||||
: fast_pair_repository_(std::move(repository)),
|
||||
on_device_destroyed_callback_(
|
||||
[this](const FastPairDevice& device) { OnDeviceDestroyed(device); }) {
|
||||
NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
platform::config_package_nearby::nearby_platform_feature::
|
||||
kEnableBleV2Gatt,
|
||||
true);
|
||||
devices_.AddObserver(&on_device_destroyed_callback_);
|
||||
seeker_ = std::make_unique<FastPairSeekerImpl>(
|
||||
FastPairSeekerImpl::ServiceCallbacks{
|
||||
.on_initial_discovery =
|
||||
@@ -81,8 +84,10 @@ absl::Status FastPairService::RegisterPluginProvider(
|
||||
absl::string_view name, std::unique_ptr<FastPairPluginProvider> provider) {
|
||||
Future<absl::Status> result;
|
||||
executor_.Execute("register-plugin", [&]() {
|
||||
bool success =
|
||||
providers_.insert({std::string(name), std::move(provider)}).second;
|
||||
bool success = plugin_states_
|
||||
.insert({std::string(name),
|
||||
PluginState{.provider = std::move(provider)}})
|
||||
.second;
|
||||
absl::Status status = success
|
||||
? absl::OkStatus()
|
||||
: absl::AlreadyExistsError(absl::StrFormat(
|
||||
@@ -97,7 +102,7 @@ absl::Status FastPairService::RegisterPluginProvider(
|
||||
absl::Status FastPairService::UnregisterPluginProvider(absl::string_view name) {
|
||||
Future<absl::Status> result;
|
||||
executor_.Execute("unregister-plugin", [&]() {
|
||||
bool success = success = providers_.erase(name);
|
||||
bool success = success = plugin_states_.erase(name);
|
||||
absl::Status status = success
|
||||
? absl::OkStatus()
|
||||
: absl::NotFoundError(absl::StrFormat(
|
||||
@@ -114,8 +119,8 @@ void FastPairService::OnInitialDiscoveryEvent(const FastPairDevice& device,
|
||||
executor_.Execute("on-initial-discovery", [this, device = &device,
|
||||
event = std::move(event)]() {
|
||||
NEARBY_LOGS(INFO) << "OnInitialDiscoveryEvent " << *device;
|
||||
for (auto& entry : providers_) {
|
||||
auto plugin = entry.second->GetPlugin(seeker_.get(), device);
|
||||
for (auto& entry : plugin_states_) {
|
||||
auto plugin = entry.second.GetPlugin(seeker_.get(), device);
|
||||
plugin->OnInitialDiscoveryEvent(event);
|
||||
}
|
||||
});
|
||||
@@ -131,5 +136,22 @@ void FastPairService::OnBatteryEvent(const FastPairDevice& device,
|
||||
void FastPairService::OnRingEvent(const FastPairDevice& device,
|
||||
RingEvent event) {}
|
||||
|
||||
void FastPairService::OnDeviceDestroyed(const FastPairDevice& device) {
|
||||
NEARBY_LOGS(INFO) << "OnDeviceDestroyed " << device;
|
||||
for (auto& entry : plugin_states_) {
|
||||
entry.second.plugins.erase(&device);
|
||||
}
|
||||
}
|
||||
|
||||
FastPairPlugin* FastPairService::PluginState::GetPlugin(
|
||||
FastPairSeeker* seeker, const FastPairDevice* device) {
|
||||
auto it = plugins.find(device);
|
||||
if (it != plugins.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
auto result = plugins.insert({device, provider->GetPlugin(seeker, device)});
|
||||
DCHECK(result.second);
|
||||
return result.first->second.get();
|
||||
}
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -57,6 +57,14 @@ class FastPairService {
|
||||
FastPairSeeker* GetSeeker() const { return seeker_.get(); }
|
||||
|
||||
private:
|
||||
struct PluginState {
|
||||
// Gets the plugin for `device`. Creates the plugin if it does not exist.
|
||||
FastPairPlugin* GetPlugin(FastPairSeeker* seeker,
|
||||
const FastPairDevice* device);
|
||||
std::unique_ptr<FastPairPluginProvider> provider;
|
||||
absl::flat_hash_map<const FastPairDevice*, std::unique_ptr<FastPairPlugin>>
|
||||
plugins;
|
||||
};
|
||||
void OnInitialDiscoveryEvent(const FastPairDevice& device,
|
||||
InitialDiscoveryEvent event);
|
||||
void OnSubsequentDiscoveryEvent(const FastPairDevice& device,
|
||||
@@ -65,12 +73,14 @@ class FastPairService {
|
||||
void OnScreenEvent(const FastPairDevice& device, ScreenEvent event);
|
||||
void OnBatteryEvent(const FastPairDevice& device, BatteryEvent event);
|
||||
void OnRingEvent(const FastPairDevice& device, RingEvent event);
|
||||
void OnDeviceDestroyed(const FastPairDevice& device);
|
||||
SingleThreadExecutor executor_;
|
||||
std::unique_ptr<FastPairSeeker> seeker_;
|
||||
absl::flat_hash_map<std::string, std::unique_ptr<FastPairPluginProvider>>
|
||||
providers_;
|
||||
// Plugin name is the key.
|
||||
absl::flat_hash_map<std::string, PluginState> plugin_states_;
|
||||
FastPairDeviceRepository devices_{&executor_};
|
||||
std::unique_ptr<FastPairRepository> fast_pair_repository_;
|
||||
FastPairDeviceRepository::RemoveDeviceCallback on_device_destroyed_callback_;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -18,6 +18,7 @@ cc_library(
|
||||
"//fastpair/repository:device_repository",
|
||||
"//fastpair/scanning:scanner",
|
||||
"//internal/platform:types",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
],
|
||||
|
||||
@@ -40,8 +40,10 @@ cc_library(
|
||||
visibility = ["//fastpair:__subpackages__"],
|
||||
deps = [
|
||||
"//fastpair/common",
|
||||
"//internal/base",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -47,7 +47,10 @@ void FastPairDeviceRepository::RemoveDevice(const FastPairDevice* device) {
|
||||
// Tasks running in the background may still be referencing `device`. Defering
|
||||
// the destruction to the background thread should prevent use-after-free
|
||||
// errors.
|
||||
executor_->Execute([fast_pair_device = std::move(fast_pair_device)]() {
|
||||
executor_->Execute([this, fast_pair_device = std::move(fast_pair_device)]() {
|
||||
for (auto* callback : observers_.GetObservers()) {
|
||||
(*callback)(*fast_pair_device);
|
||||
}
|
||||
NEARBY_LOGS(VERBOSE) << "Destroyed FP device: " << fast_pair_device;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "fastpair/common/fast_pair_device.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
|
||||
@@ -29,6 +31,12 @@ namespace fastpair {
|
||||
// Owner of `FastPairDevice` instances.
|
||||
class FastPairDeviceRepository {
|
||||
public:
|
||||
// Called on the background thread right before `device` is destroyed.
|
||||
// The callbacks are not called when FastPairDeviceRepository is
|
||||
// destructing.
|
||||
using RemoveDeviceCallback =
|
||||
absl::AnyInvocable<void(const FastPairDevice& device)>;
|
||||
|
||||
explicit FastPairDeviceRepository(SingleThreadExecutor* executor)
|
||||
: executor_(executor) {}
|
||||
|
||||
@@ -46,12 +54,20 @@ class FastPairDeviceRepository {
|
||||
// or BLE.
|
||||
std::optional<FastPairDevice*> FindDevice(absl::string_view mac_address);
|
||||
|
||||
void AddObserver(RemoveDeviceCallback* observer) {
|
||||
observers_.AddObserver(observer);
|
||||
}
|
||||
void RemoveObserver(RemoveDeviceCallback* observer) {
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
private:
|
||||
// Removes `device` from `devices_`.
|
||||
std::unique_ptr<FastPairDevice> ExtractDevice(const FastPairDevice* device);
|
||||
Mutex mutex_;
|
||||
SingleThreadExecutor* executor_;
|
||||
std::vector<std::unique_ptr<FastPairDevice>> devices_ ABSL_GUARDED_BY(mutex_);
|
||||
ObserverList<RemoveDeviceCallback> observers_;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -100,6 +100,19 @@ TEST(FastPairDeviceRepositoryTest, RemovingNonRegisteredDeviceIsSafe) {
|
||||
EXPECT_FALSE(repo.FindDevice(kBleAddress).has_value());
|
||||
}
|
||||
|
||||
TEST(FastPairDeviceRepositoryTest, RemovingDeviceCallsCallback) {
|
||||
SingleThreadExecutor executor;
|
||||
FastPairDeviceRepository repo(&executor);
|
||||
FastPairDevice* device = repo.AddDevice(std::make_unique<FastPairDevice>(
|
||||
kModelId, kBleAddress, Protocol::kFastPairInitialPairing));
|
||||
FastPairDeviceRepository::RemoveDeviceCallback callback =
|
||||
[&](const FastPairDevice& device) {};
|
||||
repo.AddObserver(&callback);
|
||||
repo.RemoveDevice(device);
|
||||
|
||||
EXPECT_FALSE(repo.FindDevice(kBleAddress).has_value());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace fastpair
|
||||
|
||||
Reference in New Issue
Block a user