diff mbox series

[BlueZ,v5,4/6] adv_monitor: Invoke DeviceFound/Lost on tracked monitors

Message ID 20211117110627.BlueZ.v5.4.If3927b0228004494a5eb09d9226370119ddf4d8b@changeid
State New
Headers show
Series [BlueZ,v5,1/6] doc: Introduce the Adv Monitor Device Found/Lost events | expand

Commit Message

Manish Mandlik Nov. 17, 2021, 7:14 p.m. UTC
This patch delivers DeviceFound/DeviceLost events to apps over D-Bus
whenever controller starts/stops tracking a device.

Tests performed:
- Add a monitor and verify that DeviceFound/DeviceLost events are
  received whenever controller starts/stops monitoring.
- Verify from logs that only one Adv Report is received from the
  controller when Sampling_Period is set to 0xFF and the
  DeviceFound/DeviceLost functionality still works as intended.
- Verify that DeviceFound/DeviceLost is reported appropriately even
  when the Active Scanning is in progress.
- Verify that the reconnection also works properly with and without
  any active Advertisement Monitor.

Reviewed-by: Miao-chen Chou <mcchou@google.com>
---

Changes in v5:
- Add this new patch in series to deliver DeviceFound/Lost to apps

 src/adv_monitor.c | 103 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 95 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/src/adv_monitor.c b/src/adv_monitor.c
index e5bdfb6ef..1a8397259 100644
--- a/src/adv_monitor.c
+++ b/src/adv_monitor.c
@@ -174,6 +174,11 @@  struct adv_rssi_filter_info {
 	int8_t rssi;
 };
 
+struct monitored_device_info {
+	uint16_t monitor_handle;	/* Kernel Monitor Handle */
+	struct btd_device *device;
+};
+
 static void monitor_device_free(void *data);
 static void adv_monitor_filter_rssi(struct adv_monitor *monitor,
 					struct btd_device *device, int8_t rssi);
@@ -1531,6 +1536,39 @@  static void adv_monitor_removed_callback(uint16_t index, uint16_t length,
 		ev->monitor_handle);
 }
 
+/* Includes found/lost device's object path into the dbus message */
+static void report_device_state_setup(DBusMessageIter *iter, void *user_data)
+{
+	const char *path = device_get_path(user_data);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+/* Invokes DeviceFound on the matched monitor */
+static void notify_device_found_per_monitor(void *data, void *user_data)
+{
+	struct adv_monitor *monitor = data;
+	struct monitored_device_info *info = user_data;
+
+	if (monitor->merged_pattern->monitor_handle == info->monitor_handle) {
+		DBG("Calling DeviceFound() on Adv Monitor of owner %s "
+		    "at path %s", monitor->app->owner, monitor->path);
+
+		g_dbus_proxy_method_call(monitor->proxy, "DeviceFound",
+					 report_device_state_setup, NULL,
+					 info->device, NULL);
+	}
+}
+
+/* Checks all monitors for match in the app to invoke DeviceFound */
+static void notify_device_found_per_app(void *data, void *user_data)
+{
+	struct adv_monitor_app *app = data;
+
+	queue_foreach(app->monitors, notify_device_found_per_monitor,
+		      user_data);
+}
+
 /* Processes Adv Monitor Device Found event from kernel */
 static void adv_monitor_device_found_callback(uint16_t index, uint16_t length,
 						const void *param,
@@ -1548,6 +1586,7 @@  static void adv_monitor_device_found_callback(uint16_t index, uint16_t length,
 	bool legacy;
 	char addr[18];
 	bool not_connectable;
+	struct monitored_device_info info;
 
 	if (length < sizeof(*ev)) {
 		btd_error(adapter_id,
@@ -1579,6 +1618,49 @@  static void adv_monitor_device_found_callback(uint16_t index, uint16_t length,
 					ev->addr.type, ev->rssi, confirm_name,
 					legacy, not_connectable, ad_data,
 					ad_data_len, true);
+
+	if (handle) {
+		DBG("Adv Monitor with handle 0x%04x started tracking "
+		    "the device %s", handle, addr);
+
+		info.device = btd_adapter_find_device(adapter, &ev->addr.bdaddr,
+						      ev->addr.type);
+		if (!info.device) {
+			btd_error(adapter_id, "Device object not found for %s",
+				  addr);
+			return;
+		}
+
+		/* Check for matched monitor in all apps */
+		info.monitor_handle = handle;
+		queue_foreach(manager->apps, notify_device_found_per_app,
+			      &info);
+	}
+}
+
+/* Invokes DeviceLost on the matched monitor */
+static void notify_device_lost_per_monitor(void *data, void *user_data)
+{
+	struct adv_monitor *monitor = data;
+	struct monitored_device_info *info = user_data;
+
+	if (monitor->merged_pattern->monitor_handle == info->monitor_handle) {
+		DBG("Calling DeviceLost() on Adv Monitor of owner %s "
+		    "at path %s", monitor->app->owner, monitor->path);
+
+		g_dbus_proxy_method_call(monitor->proxy, "DeviceLost",
+					 report_device_state_setup, NULL,
+					 info->device, NULL);
+	}
+}
+
+/* Checks all monitors for match in the app to invoke DeviceLost */
+static void notify_device_lost_per_app(void *data, void *user_data)
+{
+	struct adv_monitor_app *app = data;
+
+	queue_foreach(app->monitors, notify_device_lost_per_monitor,
+		      user_data);
 }
 
 /* Processes Adv Monitor Device Lost event from kernel */
@@ -1590,7 +1672,9 @@  static void adv_monitor_device_lost_callback(uint16_t index, uint16_t length,
 	const struct mgmt_ev_adv_monitor_device_lost *ev = param;
 	uint16_t handle = le16_to_cpu(ev->monitor_handle);
 	const uint16_t adapter_id = manager->adapter_id;
+	struct btd_adapter *adapter = manager->adapter;
 	char addr[18];
+	struct monitored_device_info info;
 
 	if (length < sizeof(*ev)) {
 		btd_error(adapter_id,
@@ -1601,6 +1685,17 @@  static void adv_monitor_device_lost_callback(uint16_t index, uint16_t length,
 	ba2str(&ev->addr.bdaddr, addr);
 	DBG("Adv Monitor with handle 0x%04x stopped tracking the device %s",
 		handle, addr);
+
+	info.device = btd_adapter_find_device(adapter, &ev->addr.bdaddr,
+					      ev->addr.type);
+	if (!info.device) {
+		btd_error(adapter_id, "Device object not found for %s", addr);
+		return;
+	}
+
+	/* Check for matched monitor in all apps */
+	info.monitor_handle = handle;
+	queue_foreach(manager->apps, notify_device_lost_per_app, &info);
 }
 
 /* Allocates a manager object */
@@ -1962,14 +2057,6 @@  static struct adv_monitor_device *monitor_device_create(
 	return dev;
 }
 
-/* Includes found/lost device's object path into the dbus message */
-static void report_device_state_setup(DBusMessageIter *iter, void *user_data)
-{
-	const char *path = device_get_path(user_data);
-
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
-}
-
 /* Handles a situation where the device goes offline/out-of-range */
 static bool handle_device_lost_timeout(gpointer user_data)
 {