Fix issue where WriteValue/AcquireNotify method comes before gatt connected 43/311943/3 accepted/tizen/7.0/unified/20240605.045148
authorWootak Jung <wootak.jung@samsung.com>
Thu, 30 May 2024 10:12:23 +0000 (19:12 +0900)
committerWootak Jung <wootak.jung@samsung.com>
Fri, 31 May 2024 04:45:28 +0000 (13:45 +0900)
Change-Id: I090e863e8c78623e7437deba118df9940dbfaaed
Signed-off-by: Wootak Jung <wootak.jung@samsung.com>
bt-oal/bluez_hal/src/bt-hal-gatt-server.c

index e3cef0a92874d0436aedade24bdd2720ec5ac6a1..1d08f50a8c4822afee2c17f9cc75bb12cb6311c8 100644 (file)
@@ -201,6 +201,17 @@ struct hal_gatts_server_register_info_t {
        bt_uuid_t app_uuid;
 };
 
+struct method_call_info {
+       GDBusConnection *connection;
+       gchar *sender;
+       gchar *object_path;
+       gchar *interface_name;
+       gchar *method_name;
+       GVariant *parameters;
+       GDBusMethodInvocation *invocation;
+       gpointer user_data;
+};
+
 static GSList * hal_gatts_server_register_list;
 
 
@@ -211,6 +222,8 @@ static GSList * hal_gatts_server_register_list;
 static int assigned_id = 0;
 static gboolean instance_id_used[BT_GATTS_MAX];
 static guint manager_id[BT_GATTS_MAX];
+static bool acquire_notify_is_pending = false;
+static bool write_value_is_pending = false;
 
 #define CHECK_BTGATT_INIT() if (_bt_hal_gatt_interface_ready() == false)\
 {\
@@ -235,6 +248,8 @@ static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
 
 static int bt_hal_gatts_get_gatt_server_instance();
 
+static gboolean __bt_pending_method_call(gpointer data);
+
 /* Introspection data for the service we are exporting */
 static const gchar service_introspection_xml[] =
 "<node name='/'>"
@@ -1341,12 +1356,36 @@ static void __bt_gatt_char_method_call(GDBusConnection *connection,
                if (prep_authorize)
                        DBG("prep_authorize = true");
 
-               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
-
                /* Check if device is already in connected list */
                conn_info = __bt_find_remote_gatt_client_info(addr);
+               if (conn_info == NULL) {
+                       ERR("Client info not found. This method call will be called again shortly");
+                       g_variant_unref(var);
 
-               if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
+                       if (write_value_is_pending) {
+                               write_value_is_pending = false;
+                               goto done;
+                       }
+
+                       struct method_call_info *info = g_malloc0(sizeof(struct method_call_info));
+                       info->connection = connection;
+                       info->sender = g_strdup(sender);
+                       info->object_path = g_strdup(object_path);
+                       info->interface_name = g_strdup(interface_name);
+                       info->method_name = g_strdup(method_name);
+                       info->parameters = g_variant_ref(parameters);
+                       g_variant_ref(parameters);
+                       info->invocation = invocation;
+                       info->user_data = user_data;
+
+                       g_timeout_add(300, __bt_pending_method_call, info);
+                       write_value_is_pending = true;
+                       return;
+               }
+               write_value_is_pending = false;
+
+               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
+               if (svc_info == NULL || event_cb == NULL) {
                        g_variant_unref(var);
                        g_dbus_method_invocation_return_value(invocation, NULL);
                        return;
@@ -1602,15 +1641,34 @@ static void __bt_gatt_char_method_call(GDBusConnection *connection,
                g_free(link);
                g_free(dev_path);
 
-               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
-
                /* Check if device is already in connected list */
                conn_info = __bt_find_remote_gatt_client_info(addr);
                if (conn_info == NULL) {
-                       ERR("Client info not found\n");
+                       ERR("Client info not found. This method call will be called again shortly");
                        g_variant_iter_free(iter);
-                       goto done;
+
+                       if (acquire_notify_is_pending) {
+                               acquire_notify_is_pending = false;
+                               goto done;
+                       }
+
+                       struct method_call_info *info = g_malloc0(sizeof(struct method_call_info));
+                       info->connection = connection;
+                       info->sender = g_strdup(sender);
+                       info->object_path = g_strdup(object_path);
+                       info->interface_name = g_strdup(interface_name);
+                       info->method_name = g_strdup(method_name);
+                       info->parameters = g_variant_ref(parameters);
+                       info->invocation = invocation;
+                       info->user_data = user_data;
+
+                       g_timeout_add(300, __bt_pending_method_call, info);
+                       acquire_notify_is_pending = true;
+                       return;
                }
+               acquire_notify_is_pending = false;
+
+               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
                if (svc_info == NULL) {
                        ERR("svc_info  info not found\n");
                        g_variant_iter_free(iter);
@@ -1647,6 +1705,30 @@ done:
        g_dbus_method_invocation_return_value(invocation, NULL);
 }
 
+static gboolean __bt_pending_method_call(gpointer data)
+{
+       struct method_call_info *info = data;
+
+       DBG("The method call was called again");
+       __bt_gatt_char_method_call(info->connection,
+                       info->sender,
+                       info->object_path,
+                       info->interface_name,
+                       info->method_name,
+                       info->parameters,
+                       info->invocation,
+                       info->user_data);
+
+       g_free(info->sender);
+       g_free(info->object_path);
+       g_free(info->interface_name);
+       g_free(info->method_name);
+       g_variant_unref(info->parameters);
+       g_free(info);
+
+       return FALSE;
+}
+
 static gboolean __bt_hal_gatt_emit_interface_removed(const char *app_path, gchar *object_path, gchar *interface)
 {
        gboolean ret;