adv_monitor: Invoke DeviceFound/Lost on tracked monitors
authorManish Mandlik <mmandlik@google.com>
Sat, 20 Nov 2021 15:29:39 +0000 (07:29 -0800)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 11 Mar 2022 13:38:38 +0000 (19:08 +0530)
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>
Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
src/adv_monitor.c

index f896604..8ccb241 100644 (file)
@@ -173,6 +173,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);
@@ -1530,6 +1535,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,
@@ -1539,6 +1577,8 @@ static void adv_monitor_device_found_callback(uint16_t index, uint16_t length,
        struct btd_adv_monitor_manager *manager = user_data;
        const uint16_t adapter_id = manager->adapter_id;
        struct btd_adapter *adapter = manager->adapter;
+       uint16_t handle = le16_to_cpu(ev->monitor_handle);
+       struct monitored_device_info info;
        const uint8_t *ad_data = NULL;
        uint16_t ad_data_len;
        uint32_t flags;
@@ -1577,6 +1617,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 */
@@ -1588,6 +1671,8 @@ 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;
+       struct monitored_device_info info;
        char addr[18];
 
        if (length < sizeof(*ev)) {
@@ -1599,6 +1684,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 */
@@ -1960,14 +2056,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)
 {