Added CAPIs for C# thread handling 33/170833/2
authorJaehyun Kim <jeik01.kim@samsung.com>
Thu, 22 Feb 2018 11:30:03 +0000 (20:30 +0900)
committerJaehyun Kim <jeik01.kim@samsung.com>
Thu, 22 Feb 2018 11:43:04 +0000 (20:43 +0900)
It is not guaranteed that the GC in C# will call wifi_manager_deinitialize
on the thread that called wifi_manager_initialize.
So I added thread-independent CAPIs for init/deinit.

Change-Id: I9d60f439e45a46a3ea1d8e292e6086f46f9bc93b
Signed-off-by: Jaehyun Kim <jeik01.kim@samsung.com>
include/network_interface.h
include/network_signal.h
include/wifi-manager-extension.h
include/wifi_internal.h
packaging/capi-network-wifi-manager.spec
src/network_interface.c
src/network_signal.c
src/wifi_internal.c
src/wifi_manager.c
tool/wifi_mgr_tool.c

index daaf1445ed9b0d3b877002ebeee99f95e34ed9ec..11c2935aad9aa533247fa48a1ffb702a89c20c17 100755 (executable)
@@ -243,6 +243,8 @@ int net_register_client_ext(net_event_cb event_cb, void *user_data);
 int net_deregister_client_ext(void);
 
 gboolean net_check_ref_count(void);
+void net_set_cs_tid(int tid);
+void net_unset_cs_tid(int tid);
 
 int net_open_connection(const char *profile_name);
 int net_close_connection(const char *profile_name);
index 122ff6bb5aba6de9730780c670e3fea099d2177c..8a9066d5005f9a69a2a79af5c3623d48656c1f2e 100755 (executable)
@@ -34,6 +34,8 @@ void _net_set_dpm_wifi_state(int state);
 int _net_get_dpm_wifi_profile_state(void);
 void _net_set_dpm_wifi_profile_state(int state);
 
+void _net_set_cs_tid(int tid);
+void _net_unset_cs_tid(int tid);
 
 #ifdef __cplusplus
 }
index 52dbedcdee182264330fddfd395231348ceff19c..0a3aae8e63b1252bb4ff2e2b5ec43fae74eeb9d0 100755 (executable)
@@ -408,6 +408,40 @@ int wifi_manager_netlink_scan_set_ssid(wifi_manager_netlink_scan_h netlink_scan,
 int wifi_manager_netlink_scan_set_vsie(wifi_manager_netlink_scan_h netlink_scan,
                const char *vsie);
 
+/**
+ * @brief Initializes Wi-Fi in C# API.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/network.get
+ * @remarks You must release @a wifi using wifi_manager_deinitialize_cs().
+ * @param[in]  tid         TID in C#
+ * @param[out] wifi        The Wi-Fi handle
+ * @return @c 0 on success, otherwise negative error value
+ * @retval #WIFI_MANAGER_ERROR_NONE                 Successful
+ * @retval #WIFI_MANAGER_ERROR_ALREADY_INITIALIZED  Already initialized
+ * @retval #WIFI_MANAGER_ERROR_INVALID_PARAMETER    Invalid parameter
+ * @retval #WIFI_MANAGER_ERROR_INVALID_OPERATION    Invalid operation
+ * @retval #WIFI_MANAGER_ERROR_OPERATION_FAILED     Operation failed
+ * @retval #WIFI_MANAGER_ERROR_PERMISSION_DENIED    Permission Denied
+ * @retval #WIFI_MANAGER_ERROR_OUT_OF_MEMORY        Out of memory
+ * @retval #WIFI_MANAGER_ERROR_NOT_SUPPORTED        Not supported
+ */
+int wifi_manager_initialize_cs(int tid, wifi_manager_h *wifi);
+
+/**
+ * @brief Deinitializes Wi-Fi in C# API.
+ * @since_tizen 5.0
+ * @param[in] tid         TID in C#
+ * @param[in] wifi        The Wi-Fi handle
+ * @return 0 on success, otherwise negative error value
+ * @retval #WIFI_MANAGER_ERROR_NONE               Successful
+ * @retval #WIFI_MANAGER_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval #WIFI_MANAGER_ERROR_INVALID_OPERATION  Invalid operation
+ * @retval #WIFI_MANAGER_ERROR_OPERATION_FAILED   Operation failed
+ * @retval #WIFI_MANAGER_ERROR_NOT_SUPPORTED      Not supported
+ */
+int wifi_manager_deinitialize_cs(int tid, wifi_manager_h wifi);
+
 /**
 * @}
 */
index 2b50d657e539c0daa6f0cc9d5338b1c8d703d508..45511e8d1f6b0d5e6b3fb3596002932c96fa6a36 100755 (executable)
@@ -200,6 +200,8 @@ typedef struct {
 /* WIFI Manager */
 int _wifi_init(void);
 bool _wifi_deinit(void);
+void _wifi_set_cs_tid(int tid);
+void _wifi_unset_cs_tid(int tid);
 
 int _wifi_create_handle(wifi_manager_h *wifi);
 int _wifi_add_to_handle_list(wifi_manager_h* wifi);
index c30ed0c3611b32de57102be0d018f49f1f25a59c..e6466ddcd0fb84a2f62839f4e52200e7aeec1aa3 100755 (executable)
@@ -1,6 +1,6 @@
 Name:          capi-network-wifi-manager
 Summary:       Network Wi-Fi library in TIZEN C API
-Version:       1.0.29
+Version:       1.0.30
 Release:       1
 Group:         System/Network
 License:       Apache-2.0
index 79fabc3ade08a0c958273c0084b60373d2e35fba..26353fb070edb2a7be795d9221b24f74e1a02ac2 100755 (executable)
@@ -2821,6 +2821,21 @@ gboolean net_check_ref_count(void)
        return FALSE; //LCOV_EXCL_LINE
 }
 
+void net_set_cs_tid(int tid)
+{
+       if (NetworkInfo.ref_count < 1) {
+               WIFI_LOG(WIFI_ERROR, "Application is not registered"); //LCOV_EXCL_LINE
+               return;
+       }
+
+       _net_set_cs_tid(tid);
+}
+
+void net_unset_cs_tid(int tid)
+{
+       _net_unset_cs_tid(tid);
+}
+
 int net_open_connection(const char *profile_name)
 {
        __NETWORK_FUNC_ENTER__;
index 375fc0ff962f006f5a995db8de91355e5fb75b28..49fc4853bfc9b33c52ab3c828a87c6605bb03c1c 100755 (executable)
@@ -42,6 +42,18 @@ static __thread guint gdbus_conn_subscribe_id_netconfig = 0;
 static __thread int net_dpm_wifi_state = -1;
 static __thread int net_dpm_wifi_profile_state = -1;
 
+struct cs_tid_info {
+       int tid;
+       guint subscribe_id_connman_state;
+       guint subscribe_id_connman_error;
+       guint subscribe_id_connman_scandone;
+       guint subscribe_id_connman_scanstarted;
+       guint subscribe_id_netconfig_wifi;
+       guint subscribe_id_netconfig;
+};
+
+static GSList *cs_tid_list = NULL;
+
 static int __net_dbus_get_bssid_list();
 
 //LCOV_EXCL_START
@@ -1460,6 +1472,91 @@ void _net_set_dpm_wifi_profile_state(int state)
 }
 //LCOV_EXCL_STOP
 
+void _net_set_cs_tid(int tid)
+{
+       GSList *list;
+       struct cs_tid_info *tid_info = NULL;
+       struct cs_tid_info *data = NULL;
+
+       if (cs_tid_list) {
+               for (list = cs_tid_list; list; list = list->next) {
+                       data = (struct cs_tid_info *)list->data;
+                       if (tid == data->tid) {
+                               tid_info = data;
+                               break;
+                       }
+               }
+       }
+
+       if (!tid_info) {
+               tid_info = (struct cs_tid_info *)g_try_malloc0(sizeof(struct cs_tid_info));
+               if (!tid_info) {
+                       WIFI_LOG(WIFI_ERROR, "Out of memory, tid %d", tid);
+                       return;
+               }
+
+               tid_info->tid = tid;
+               cs_tid_list = g_slist_prepend(cs_tid_list, tid_info);
+       }
+
+       tid_info->subscribe_id_connman_state = gdbus_conn_subscribe_id_connman_state;
+       tid_info->subscribe_id_connman_error = gdbus_conn_subscribe_id_connman_error;
+       tid_info->subscribe_id_connman_scandone = gdbus_conn_subscribe_id_connman_scandone;
+       tid_info->subscribe_id_connman_scanstarted = gdbus_conn_subscribe_id_connman_scanstarted;
+       tid_info->subscribe_id_netconfig_wifi = gdbus_conn_subscribe_id_netconfig_wifi;
+       tid_info->subscribe_id_netconfig = gdbus_conn_subscribe_id_netconfig;
+
+       WIFI_LOG(WIFI_INFO, "tid %d, tid_info %p", tid, tid_info);
+}
+
+void _net_unset_cs_tid(int tid)
+{
+       GSList *list;
+       struct cs_tid_info *tid_info = NULL;
+       struct cs_tid_info *data = NULL;
+
+       if (cs_tid_list) {
+               for (list = cs_tid_list; list; list = list->next) {
+                       data = (struct cs_tid_info *)list->data;
+                       if (tid == data->tid) {
+                               tid_info = data;
+                               break;
+                       }
+               }
+       }
+
+       if (!tid_info) {
+               WIFI_LOG(WIFI_ERROR, "No tid_info, tid %d", tid);
+               return;
+       }
+
+       GDBusConnection *connection;
+       GError *error = NULL;
+
+       connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+       if (connection == NULL) {
+               if (error != NULL) {
+                       WIFI_LOG(WIFI_ERROR,
+                               "Failed to connect to the D-BUS daemon [%s]", error->message);
+                       g_error_free(error);
+               }
+               return;
+       }
+
+       g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_connman_state);
+       g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_connman_error);
+       g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_connman_scandone);
+       g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_connman_scanstarted);
+       g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_netconfig_wifi);
+       g_dbus_connection_signal_unsubscribe(connection, tid_info->subscribe_id_netconfig);
+       g_object_unref(connection);
+
+       WIFI_LOG(WIFI_INFO, "tid %d, tid_info %p", tid, tid_info);
+
+       cs_tid_list = g_slist_remove(cs_tid_list, tid_info);
+       g_free(tid_info);
+}
+
 int _net_deregister_signal(void)
 {
        __NETWORK_FUNC_ENTER__;
index fd2aba069dc009e3c880e0358e0319c3e4b2759c..6ab7b7952f66a9e8b0a662c49233dfdba00b76a5 100755 (executable)
@@ -1369,6 +1369,16 @@ bool _wifi_deinit(void)
        return true;
 }
 
+void _wifi_set_cs_tid(int tid)
+{
+       net_set_cs_tid(tid);
+}
+
+void _wifi_unset_cs_tid(int tid)
+{
+       net_unset_cs_tid(tid);
+}
+
 int _wifi_activate(wifi_manager_h wifi, wifi_manager_activated_cb callback,
                gboolean wifi_picker_test, void *user_data)
 {
index 301f386d5857aedc3a154a4279c3c92127b29096..72640da7d42297525c91904593dcd549983c7649 100755 (executable)
@@ -246,6 +246,34 @@ EXPORT_API int wifi_manager_deinitialize(wifi_manager_h wifi)
        return WIFI_MANAGER_ERROR_NONE;
 }
 
+EXPORT_API int wifi_manager_initialize_cs(int tid, wifi_manager_h *wifi)
+{
+       __NETWORK_CAPI_FUNC_ENTER__;
+
+       int rv;
+
+       rv = wifi_manager_initialize(wifi);
+
+       if (rv == WIFI_MANAGER_ERROR_NONE)
+               _wifi_set_cs_tid(tid);
+
+       __NETWORK_CAPI_FUNC_EXIT__;
+       return rv;
+}
+
+EXPORT_API int wifi_manager_deinitialize_cs(int tid, wifi_manager_h wifi)
+{
+       __NETWORK_CAPI_FUNC_ENTER__;
+
+       int rv;
+
+       _wifi_unset_cs_tid(tid);
+       rv = wifi_manager_deinitialize(wifi);
+
+       __NETWORK_CAPI_FUNC_EXIT__;
+       return rv;
+}
+
 EXPORT_API int wifi_manager_activate(wifi_manager_h wifi,
                wifi_manager_activated_cb callback, void *user_data)
 {
index 8602a0db1790161fd8128a5f51f0567c32aacb8d..b31393b02db7e496b9fc1e3d526e240709a2c784 100755 (executable)
@@ -31,6 +31,7 @@
 wifi_manager_h g_wifi_h = NULL;
 wifi_manager_h g_wifi2_h = NULL;
 wifi_manager_device_state_e g_device_state = WIFI_MANAGER_DEVICE_STATE_DEACTIVATED;
+static int cs_tid = 0;
 
 extern struct menu_data menu_public[];
 extern struct menu_data menu_extension[];
@@ -185,12 +186,78 @@ static int _test_wifi_mgr_initialize(MManager *mm, struct menu_data *menu)
        return ret;
 }
 
+static int _test_wifi_mgr_initialize_cs(MManager *mm, struct menu_data *menu)
+{
+       int ret = WIFI_MANAGER_ERROR_NONE;
+       bool state = FALSE;
+
+       cs_tid = get_tid();
+
+       if (!g_wifi_h) {
+               ret = wifi_manager_initialize_cs(cs_tid, &g_wifi_h);
+               if (ret == WIFI_MANAGER_ERROR_NONE) {
+                       wifi_manager_set_device_state_changed_cb(g_wifi_h, __test_device_state_cb, "1");
+                       wifi_manager_set_scan_state_changed_cb(g_wifi_h, __test_scan_changed_cb, "1");
+                       wifi_manager_set_connection_state_changed_cb(g_wifi_h, __test_connection_state_cb, "1");
+                       wifi_manager_set_rssi_level_changed_cb(g_wifi_h, __test_rssi_level_cb, "1");
+                       wifi_manager_set_background_scan_cb(g_wifi_h, __test_bg_scan_completed_cb, "1");
+                       wifi_manager_set_ip_conflict_cb(g_wifi_h, __test_ip_conflict_cb, "1");
+                       wifi_manager_set_module_state_changed_cb(g_wifi_h, __test_get_wifi_module_state_cb, "1");
+
+                       wifi_manager_tdls_set_state_changed_cb(g_wifi_h, __test_tdls_state_cb, "1");
+                       wifi_manager_tdls_set_discovered_cb(g_wifi_h, __test_tdls_discover_cb, "1");
+
+                       msg(LOG_GREEN "Success to initialize wifi [1] handle [%p]" LOG_END, g_wifi_h);
+               } else {
+                       msg("Failed to initialize wifi handle " LOG_RED "[%s]" LOG_END,
+                               test_wifi_mgr_convert_error_to_string(ret));
+               }
+       }
+
+       if (!g_wifi2_h) {
+               ret = wifi_manager_initialize_cs(cs_tid, &g_wifi2_h);
+               if (ret == WIFI_MANAGER_ERROR_NONE) {
+                       wifi_manager_set_device_state_changed_cb(g_wifi2_h, __test_device_state_cb, "2");
+                       wifi_manager_set_scan_state_changed_cb(g_wifi2_h, __test_scan_changed_cb, "2");
+                       wifi_manager_set_connection_state_changed_cb(g_wifi2_h, __test_connection_state_cb, "2");
+                       wifi_manager_set_rssi_level_changed_cb(g_wifi2_h, __test_rssi_level_cb, "2");
+                       wifi_manager_set_background_scan_cb(g_wifi2_h, __test_bg_scan_completed_cb, "2");
+                       wifi_manager_set_ip_conflict_cb(g_wifi2_h, __test_ip_conflict_cb, "2");
+                       wifi_manager_set_module_state_changed_cb(g_wifi2_h, __test_get_wifi_module_state_cb, "2");
+
+                       wifi_manager_tdls_set_state_changed_cb(g_wifi2_h, __test_tdls_state_cb, "2");
+                       wifi_manager_tdls_set_discovered_cb(g_wifi2_h, __test_tdls_discover_cb, "2");
+
+                       msg(LOG_GREEN "Success to initialize wifi [2] handle [%p]" LOG_END, g_wifi2_h);
+               } else {
+                       msg("Failed to initialize wifi [2] handle " LOG_RED "[%s]" LOG_END,
+                               test_wifi_mgr_convert_error_to_string(ret));
+               }
+       }
+
+       ret = wifi_manager_is_activated(g_wifi_h, &state);
+       if (ret == WIFI_MANAGER_ERROR_NONE) {
+               g_device_state = state;
+               msg("Wi-Fi device state " LOG_CYAN "[%s]" LOG_END,
+                       test_wifi_mgr_device_state_to_string(g_device_state));
+       } else {
+               msg("Failed to get Wi-Fi device state " LOG_RED "[%s]" LOG_END,
+                       test_wifi_mgr_convert_error_to_string(ret));
+       }
+
+       return ret;
+}
+
 static int _test_wifi_mgr_deinitialize(void)
 {
        int ret = WIFI_MANAGER_ERROR_NONE;
 
        if (g_wifi_h) {
-               ret = wifi_manager_deinitialize(g_wifi_h);
+               if (cs_tid)
+                       ret = wifi_manager_deinitialize_cs(cs_tid, g_wifi_h);
+               else
+                       ret = wifi_manager_deinitialize(g_wifi_h);
+
                if (ret == WIFI_MANAGER_ERROR_NONE)
                        msg(LOG_GREEN "Succeeded to deinitialize wifi handle" LOG_END);
                else
@@ -199,7 +266,11 @@ static int _test_wifi_mgr_deinitialize(void)
        }
 
        if (g_wifi2_h) {
-               ret = wifi_manager_deinitialize(g_wifi2_h);
+               if (cs_tid)
+                       ret = wifi_manager_deinitialize_cs(cs_tid, g_wifi2_h);
+               else
+                       ret = wifi_manager_deinitialize(g_wifi2_h);
+
                if (ret == WIFI_MANAGER_ERROR_NONE)
                        msg(LOG_GREEN "Succeeded to deinitialize wifi2 handle" LOG_END);
                else
@@ -207,10 +278,12 @@ static int _test_wifi_mgr_deinitialize(void)
                                test_wifi_mgr_convert_error_to_string(ret));
        }
 
+       cs_tid = 0;
+
        return ret;
 }
 
-static gboolean _test_wifi_mgr_create_init_menu(struct menu_data init_menu[1])
+static gboolean _test_wifi_mgr_create_init_menu(struct menu_data init_menu[2])
 {
        init_menu[0].key = "1";
        init_menu[0].title = LOG_YELLOW "Wifi Mgr Init" LOG_END;
@@ -218,6 +291,12 @@ static gboolean _test_wifi_mgr_create_init_menu(struct menu_data init_menu[1])
        init_menu[0].callback = _test_wifi_mgr_initialize;
        init_menu[0].data = NULL;
 
+       init_menu[1].key = "2";
+       init_menu[1].title = LOG_YELLOW "Wifi Mgr Init for C#" LOG_END;
+       init_menu[1].sub_menu = menu_main;
+       init_menu[1].callback = _test_wifi_mgr_initialize_cs;
+       init_menu[1].data = NULL;
+
        return TRUE;
 }
 
@@ -495,7 +574,7 @@ int main(int arg, char **argv)
        GMainLoop *mainloop = NULL;
        GIOChannel *channel = g_io_channel_unix_new(STDIN_FILENO);
        MManager *manager;
-       struct menu_data init_menu[1+1] = { {NULL, NULL, } };
+       struct menu_data init_menu[2+1] = { {NULL, NULL, NULL, } };
 
 #if !GLIB_CHECK_VERSION(2, 35, 0)
        g_type_init();