diff --git a/internal/base/BUILD b/internal/base/BUILD index 69faa567..a7cc6631 100644 --- a/internal/base/BUILD +++ b/internal/base/BUILD @@ -13,6 +13,7 @@ cc_library( visibility = [ "//fastpair:__subpackages__", "//internal:__pkg__", + "//internal/platform:__pkg__", "//location/nearby/cpp/fastpair:__subpackages__", "//location/nearby/cpp/sharing:__subpackages__", ], diff --git a/internal/platform/BUILD b/internal/platform/BUILD index b6508e38..b3479b25 100644 --- a/internal/platform/BUILD +++ b/internal/platform/BUILD @@ -409,9 +409,11 @@ cc_library( ":logging", ":types", ":uuid", + "//internal/base", "//internal/platform/implementation:comm", "//internal/platform/implementation:platform", "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", diff --git a/internal/platform/bluetooth_classic.cc b/internal/platform/bluetooth_classic.cc index c30fdf06..beade20d 100644 --- a/internal/platform/bluetooth_classic.cc +++ b/internal/platform/bluetooth_classic.cc @@ -19,7 +19,12 @@ namespace nearby { -BluetoothClassicMedium::~BluetoothClassicMedium() { StopDiscovery(); } +BluetoothClassicMedium::~BluetoothClassicMedium() { + if (!observer_list_.empty()) { + impl_->RemoveObserver(this); + } + StopDiscovery(); +} BluetoothSocket BluetoothClassicMedium::ConnectToService( BluetoothDevice& remote_device, const std::string& service_uuid, @@ -94,4 +99,54 @@ bool BluetoothClassicMedium::StopDiscovery() { return impl_->StopDiscovery(); } +void BluetoothClassicMedium::AddObserver(Observer* observer) { + MutexLock lock(&mutex_); + if (observer_list_.empty()) { + impl_->AddObserver(this); + } + observer_list_.AddObserver(observer); +} +void BluetoothClassicMedium::RemoveObserver(Observer* observer) { + MutexLock lock(&mutex_); + observer_list_.RemoveObserver(observer); + if (observer_list_.empty()) { + impl_->RemoveObserver(this); + } +} + +// api::BluetoothClassicMedium::Observer methods +void BluetoothClassicMedium::DeviceAdded(api::BluetoothDevice& device) { + BluetoothDevice bt_device(&device); + for (auto* observer : observer_list_.GetObservers()) { + observer->DeviceAdded(bt_device); + } +} +void BluetoothClassicMedium::DeviceRemoved(api::BluetoothDevice& device) { + BluetoothDevice bt_device(&device); + for (auto* observer : observer_list_.GetObservers()) { + observer->DeviceRemoved(bt_device); + } +} +void BluetoothClassicMedium::DeviceAddressChanged( + api::BluetoothDevice& device, absl::string_view old_address) { + BluetoothDevice bt_device(&device); + for (auto* observer : observer_list_.GetObservers()) { + observer->DeviceAddressChanged(bt_device, old_address); + } +} +void BluetoothClassicMedium::DevicePairedChanged(api::BluetoothDevice& device, + bool new_paired_status) { + BluetoothDevice bt_device(&device); + for (auto* observer : observer_list_.GetObservers()) { + observer->DevicePairedChanged(bt_device, new_paired_status); + } +} +void BluetoothClassicMedium::DeviceConnectedStateChanged( + api::BluetoothDevice& device, bool connected) { + BluetoothDevice bt_device(&device); + for (auto* observer : observer_list_.GetObservers()) { + observer->DeviceConnectedStateChanged(bt_device, connected); + } +} + } // namespace nearby diff --git a/internal/platform/bluetooth_classic.h b/internal/platform/bluetooth_classic.h index c9a8180e..319d14f5 100644 --- a/internal/platform/bluetooth_classic.h +++ b/internal/platform/bluetooth_classic.h @@ -19,6 +19,8 @@ #include #include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" +#include "internal/base/observer_list.h" #include "internal/platform/bluetooth_adapter.h" #include "internal/platform/byte_array.h" #include "internal/platform/cancellation_flag.h" @@ -126,7 +128,8 @@ class BluetoothServerSocket final { // Container of operations that can be performed over the Bluetooth Classic // medium. -class BluetoothClassicMedium final { +class BluetoothClassicMedium final + : public api::BluetoothClassicMedium::Observer { public: using Platform = api::ImplementationPlatform; struct DiscoveryCallback { @@ -148,11 +151,39 @@ class BluetoothClassicMedium final { BluetoothDevice device; }; + class Observer { + public: + virtual ~Observer() = default; + + // Called when a new `device` is added. The `device` parameter becomes + // invalid after the call. + virtual void DeviceAdded(BluetoothDevice& device) {} + + // Called when `device` is removed. The `device` parameter becomes invalid + // after the call. + virtual void DeviceRemoved(BluetoothDevice& device) {} + + // Called when the address of `device` changed due to pairing. The + // `device` parameter becomes invalid after the call. + virtual void DeviceAddressChanged(BluetoothDevice& device, + absl::string_view old_address) {} + + // Called when the paired property of `device` changed. The `device` + // parameter becomes invalid after the call. + virtual void DevicePairedChanged(BluetoothDevice& device, + bool new_paired_status) {} + + // Called when `device` has connected or disconnected. The `device` + // parameter becomes invalid after the call. + virtual void DeviceConnectedStateChanged(BluetoothDevice& device, + bool connected) {} + }; + explicit BluetoothClassicMedium(BluetoothAdapter& adapter) : impl_(Platform::CreateBluetoothClassicMedium(adapter.GetImpl())), adapter_(adapter) {} - ~BluetoothClassicMedium(); + ~BluetoothClassicMedium() override; // NOTE(DiscoveryCallback): // BluetoothDevice is a proxy object created as a result of BT discovery. @@ -217,6 +248,23 @@ class BluetoothClassicMedium final { return BluetoothDevice(impl_->GetRemoteDevice(mac_address)); } + // Adds an observer. `observer` must be valid until RemoveObserver is called, + // or BluetoothClassicMedium is destroyed. + void AddObserver(Observer* observer); + + // Removes an observer. It's OK to remove an unregistered observer. + void RemoveObserver(Observer* observer); + + // api::BluetoothClassicMedium::Observer methods + void DeviceAdded(api::BluetoothDevice& device) override; + void DeviceRemoved(api::BluetoothDevice& device) override; + void DeviceAddressChanged(api::BluetoothDevice& device, + absl::string_view old_address) override; + void DevicePairedChanged(api::BluetoothDevice& device, + bool new_paired_status) override; + void DeviceConnectedStateChanged(api::BluetoothDevice& device, + bool connected) override; + private: Mutex mutex_; std::unique_ptr impl_; @@ -226,6 +274,7 @@ class BluetoothClassicMedium final { devices_ ABSL_GUARDED_BY(mutex_); DiscoveryCallback discovery_callback_ ABSL_GUARDED_BY(mutex_); bool discovery_enabled_ ABSL_GUARDED_BY(mutex_) = false; + ObserverList observer_list_; }; } // namespace nearby diff --git a/internal/platform/implementation/bluetooth_classic.h b/internal/platform/implementation/bluetooth_classic.h index 5dfba4ef..7f8f9cf3 100644 --- a/internal/platform/implementation/bluetooth_classic.h +++ b/internal/platform/implementation/bluetooth_classic.h @@ -111,6 +111,29 @@ class BluetoothClassicMedium { DefaultCallback(); }; + class Observer { + public: + virtual ~Observer() = default; + + // Called when a new `device` is added to the adapter. + virtual void DeviceAdded(BluetoothDevice& device) {} + + // Called when `device` is removed from the adapter. + virtual void DeviceRemoved(BluetoothDevice& device) {} + + // Called when the address of `device` changed due to pairing. + virtual void DeviceAddressChanged(BluetoothDevice& device, + absl::string_view old_address) {} + + // Called when the paired property of `device` changed. + virtual void DevicePairedChanged(BluetoothDevice& device, + bool new_paired_status) {} + + // Called when `device` has connected or disconnected. + virtual void DeviceConnectedStateChanged(BluetoothDevice& device, + bool connected) {} + }; + // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery() // // Returns true once the process of discovery has been initiated. @@ -152,6 +175,9 @@ class BluetoothClassicMedium { const std::string& service_name, const std::string& service_uuid) = 0; virtual BluetoothDevice* GetRemoteDevice(const std::string& mac_address) = 0; + + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; }; } // namespace api diff --git a/internal/platform/implementation/g3/bluetooth_classic.cc b/internal/platform/implementation/g3/bluetooth_classic.cc index a8d2c93b..b8544aba 100644 --- a/internal/platform/implementation/g3/bluetooth_classic.cc +++ b/internal/platform/implementation/g3/bluetooth_classic.cc @@ -277,5 +277,14 @@ api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice( return env.FindBluetoothDevice(mac_address); } +void BluetoothClassicMedium::AddObserver( + api::BluetoothClassicMedium::Observer* observer) { + // TODO(b/269521993): Implement observer callbacks. +} +void BluetoothClassicMedium::RemoveObserver( + api::BluetoothClassicMedium::Observer* observer) { + // TODO(b/269521993): Implement observer callbacks. +} + } // namespace g3 } // namespace nearby diff --git a/internal/platform/implementation/g3/bluetooth_classic.h b/internal/platform/implementation/g3/bluetooth_classic.h index 668f8cec..1db7af17 100644 --- a/internal/platform/implementation/g3/bluetooth_classic.h +++ b/internal/platform/implementation/g3/bluetooth_classic.h @@ -236,6 +236,9 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { api::BluetoothDevice* GetRemoteDevice( const std::string& mac_address) override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + private: absl::Mutex mutex_; BluetoothAdapter* adapter_; // Our device adapter; read-only. diff --git a/internal/platform/implementation/windows/bluetooth_classic_medium.h b/internal/platform/implementation/windows/bluetooth_classic_medium.h index 35b6ba6f..a9f2b4ef 100644 --- a/internal/platform/implementation/windows/bluetooth_classic_medium.h +++ b/internal/platform/implementation/windows/bluetooth_classic_medium.h @@ -148,6 +148,15 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { api::BluetoothDevice* GetRemoteDevice(const std::string& mac_address) override ABSL_LOCKS_EXCLUDED(mutex_); + void AddObserver(Observer* observer) override { + // TODO(b/269521993): Implement. + } + + // Removes an observer. It's OK to remove an unregistered observer. + void RemoveObserver(Observer* observer) override { + // TODO(b/269521993): Implement. + } + private: bool StartScanning() ABSL_SHARED_LOCKS_REQUIRED(mutex_); bool StopScanning() ABSL_SHARED_LOCKS_REQUIRED(mutex_);