aboutsummaryrefslogtreecommitdiffstats
path: root/components/bluetooth/adapter.rs
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2024-01-09 10:13:41 +0100
committerGitHub <noreply@github.com>2024-01-09 09:13:41 +0000
commit6a804cd775e3976103269ac54ae997a3accc8618 (patch)
tree1a125d1901e5aa3cc98a1f5beabebd927a3b9472 /components/bluetooth/adapter.rs
parentfddc4a430fca591152c69f0793ab946dcdc81617 (diff)
downloadservo-6a804cd775e3976103269ac54ae997a3accc8618.tar.gz
servo-6a804cd775e3976103269ac54ae997a3accc8618.zip
Integrate the `devices` respository (#30974)
Despite the name of this dependency, it only handles bluetooth. Because it's a separate repository. Integrating it, allows changes here to be tested more consistently. In addition, it's likely that new bluetooth libraries will allow removing the majority of the platform-specific code in this directory. This is based on the version of this dependency from: https://github.com/servo/devices/pull/34
Diffstat (limited to 'components/bluetooth/adapter.rs')
-rw-r--r--components/bluetooth/adapter.rs408
1 files changed, 408 insertions, 0 deletions
diff --git a/components/bluetooth/adapter.rs b/components/bluetooth/adapter.rs
new file mode 100644
index 00000000000..b5cd71b4543
--- /dev/null
+++ b/components/bluetooth/adapter.rs
@@ -0,0 +1,408 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::error::Error;
+use std::sync::Arc;
+
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_adapter::Adapter as BluetoothAdapterAndroid;
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_device::Device as BluetoothDeviceAndroid;
+#[cfg(all(target_os = "android", feature = "bluetooth"))]
+use blurdroid::bluetooth_discovery_session::DiscoverySession as BluetoothDiscoverySessionAndroid;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothAdapter as BluetoothAdapterMac;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothDevice as BluetoothDeviceMac;
+#[cfg(all(target_os = "macos", feature = "bluetooth"))]
+use blurmac::BluetoothDiscoverySession as BluetoothDiscoverySessionMac;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_adapter::FakeBluetoothAdapter;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_device::FakeBluetoothDevice;
+#[cfg(feature = "bluetooth-test")]
+use blurmock::fake_discovery_session::FakeBluetoothDiscoverySession;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_adapter::BluetoothAdapter as BluetoothAdapterBluez;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_device::BluetoothDevice as BluetoothDeviceBluez;
+#[cfg(all(target_os = "linux", feature = "bluetooth"))]
+use blurz::bluetooth_discovery_session::BluetoothDiscoverySession as BluetoothDiscoverySessionBluez;
+
+use super::bluetooth::{BluetoothDevice, BluetoothDiscoverySession};
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothDevice as BluetoothDeviceEmpty;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::BluetoothDiscoverySession as BluetoothDiscoverySessionEmpty;
+#[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+)))]
+use super::empty::EmptyAdapter as BluetoothAdapterEmpty;
+use super::macros::get_inner_and_call;
+#[cfg(feature = "bluetooth-test")]
+use super::macros::get_inner_and_call_test_func;
+
+#[derive(Clone, Debug)]
+pub enum BluetoothAdapter {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ Bluez(Arc<BluetoothAdapterBluez>),
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ Android(Arc<BluetoothAdapterAndroid>),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ Mac(Arc<BluetoothAdapterMac>),
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ Empty(Arc<BluetoothAdapterEmpty>),
+ #[cfg(feature = "bluetooth-test")]
+ Mock(Arc<FakeBluetoothAdapter>),
+}
+
+impl BluetoothAdapter {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ let bluez_adapter = BluetoothAdapterBluez::init()?;
+ Ok(Self::Bluez(Arc::new(bluez_adapter)))
+ }
+
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ let blurdroid_adapter = BluetoothAdapterAndroid::get_adapter()?;
+ Ok(Self::Android(Arc::new(blurdroid_adapter)))
+ }
+
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ let mac_adapter = BluetoothAdapterMac::init()?;
+ Ok(Self::Mac(Arc::new(mac_adapter)))
+ }
+
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ let adapter = BluetoothAdapterEmpty::init()?;
+ Ok(Self::Empty(Arc::new(adapter)))
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn new_mock() -> Result<BluetoothAdapter, Box<dyn Error>> {
+ Ok(Self::Mock(FakeBluetoothAdapter::new_empty()))
+ }
+
+ pub fn get_id(&self) -> String {
+ get_inner_and_call!(self, BluetoothAdapter, get_id)
+ }
+
+ pub fn get_devices(&self) -> Result<Vec<BluetoothDevice>, Box<dyn Error>> {
+ match self {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ BluetoothAdapter::Bluez(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Bluez(BluetoothDeviceBluez::new_empty(
+ self.0.clone(),
+ device,
+ ))
+ })
+ .collect())
+ },
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ BluetoothAdapter::Android(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Android(BluetoothDeviceAndroid::new_empty(
+ self.0.clone(),
+ device,
+ ))
+ })
+ .collect())
+ },
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ BluetoothAdapter::Mac(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Mac(Arc::new(BluetoothDeviceMac::new(
+ inner.clone(),
+ device,
+ )))
+ })
+ .collect())
+ },
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ BluetoothAdapter::Empty(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Empty(Arc::new(BluetoothDeviceEmpty::new(device)))
+ })
+ .collect())
+ },
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothAdapter::Mock(inner) => {
+ let device_list = inner.get_device_list()?;
+ Ok(device_list
+ .into_iter()
+ .map(|device| {
+ BluetoothDevice::Mock(FakeBluetoothDevice::new_empty(inner.clone(), device))
+ })
+ .collect())
+ },
+ }
+ }
+
+ pub fn get_device(&self, address: String) -> Result<Option<BluetoothDevice>, Box<dyn Error>> {
+ let devices = self.get_devices()?;
+ for device in devices {
+ if device.get_address()? == address {
+ return Ok(Some(device));
+ }
+ }
+ Ok(None)
+ }
+
+ pub fn create_mock_device(&self, _device: String) -> Result<BluetoothDevice, Box<dyn Error>> {
+ match self {
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothAdapter::Mock(inner) => Ok(BluetoothDevice::Mock(
+ FakeBluetoothDevice::new_empty(inner.clone(), _device),
+ )),
+ _ => Err(Box::from(
+ "Error! Test functions are not supported on real devices!",
+ )),
+ }
+ }
+
+ pub fn create_discovery_session(&self) -> Result<BluetoothDiscoverySession, Box<dyn Error>> {
+ let discovery_session = match self {
+ #[cfg(all(target_os = "linux", feature = "bluetooth"))]
+ BluetoothAdapter::Bluez(inner) => {
+ BluetoothDiscoverySession::Bluez(Arc::new(
+ BluetoothDiscoverySessionBluez::create_session(inner.get_id())?,
+ ));
+ },
+ #[cfg(all(target_os = "android", feature = "bluetooth"))]
+ BluetoothAdapter::Android(inner) => BluetoothDiscoverySession::Android(Arc::new(
+ BluetoothDiscoverySessionAndroid::create_session(inner.clone())?,
+ )),
+ #[cfg(all(target_os = "macos", feature = "bluetooth"))]
+ BluetoothAdapter::Mac(_) => {
+ BluetoothDiscoverySession::Mac(Arc::new(BluetoothDiscoverySessionMac {}))
+ },
+ #[cfg(not(any(
+ all(target_os = "linux", feature = "bluetooth"),
+ all(target_os = "android", feature = "bluetooth"),
+ all(target_os = "macos", feature = "bluetooth")
+ )))]
+ BluetoothAdapter::Empty(_) => {
+ BluetoothDiscoverySession::Empty(Arc::new(BluetoothDiscoverySessionEmpty {}))
+ },
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothAdapter::Mock(inner) => BluetoothDiscoverySession::Mock(Arc::new(
+ FakeBluetoothDiscoverySession::create_session(inner.clone())?,
+ )),
+ };
+ Ok(discovery_session)
+ }
+
+ pub fn get_address(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_address)
+ }
+
+ pub fn get_name(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_name)
+ }
+
+ pub fn get_alias(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_alias)
+ }
+
+ pub fn get_class(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_class)
+ }
+
+ pub fn is_powered(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, is_powered)
+ }
+
+ pub fn is_discoverable(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, is_discoverable)
+ }
+
+ pub fn is_pairable(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, is_pairable)
+ }
+
+ pub fn get_pairable_timeout(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_pairable_timeout)
+ }
+
+ pub fn get_discoverable_timeout(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_discoverable_timeout)
+ }
+
+ pub fn is_discovering(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, is_discovering)
+ }
+
+ pub fn get_uuids(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_uuids)
+ }
+
+ pub fn get_vendor_id_source(&self) -> Result<String, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_vendor_id_source)
+ }
+
+ pub fn get_vendor_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_vendor_id)
+ }
+
+ pub fn get_product_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_product_id)
+ }
+
+ pub fn get_device_id(&self) -> Result<u32, Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_device_id)
+ }
+
+ pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<dyn Error>> {
+ get_inner_and_call!(self, BluetoothAdapter, get_modalias)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_id(&self, id: String) -> Result<(), Box<dyn Error>> {
+ match self {
+ #[cfg(feature = "bluetooth-test")]
+ BluetoothAdapter::Mock(inner) => Ok(inner.set_id(id)),
+ _ => Err(Box::from(
+ "Error! Test functions are not supported on real devices!",
+ )),
+ }
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_address(&self, address: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_address, address)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_name(&self, name: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_name, name)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_alias(&self, alias: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_alias, alias)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_class(&self, class: u32) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_class, class)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_powered(&self, powered: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_powered, powered)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn is_present(&self) -> Result<bool, Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, is_present)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_present(&self, present: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_present, present)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_discoverable(&self, discoverable: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_discoverable, discoverable)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_pairable(&self, pairable: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_pairable, pairable)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_pairable_timeout(&self, timeout: u32) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_pairable_timeout, timeout)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_can_start_discovery(&self, can_start_discovery: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(
+ self,
+ BluetoothAdapter,
+ set_can_start_discovery,
+ can_start_discovery
+ )
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_discoverable_timeout(&self, timeout: u32) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_discoverable_timeout, timeout)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_discovering(&self, discovering: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_discovering, discovering)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_can_stop_discovery(&self, can_stop_discovery: bool) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(
+ self,
+ BluetoothAdapter,
+ set_can_stop_discovery,
+ can_stop_discovery
+ )
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_uuids(&self, uuids: Vec<String>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_uuids, uuids)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_modalias(&self, modalias: String) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_modalias, modalias)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn get_ad_datas(&self) -> Result<Vec<String>, Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, get_ad_datas)
+ }
+
+ #[cfg(feature = "bluetooth-test")]
+ pub fn set_ad_datas(&self, ad_datas: Vec<String>) -> Result<(), Box<dyn Error>> {
+ get_inner_and_call_test_func!(self, BluetoothAdapter, set_ad_datas, ad_datas)
+ }
+}