From: JinWang An Date: Fri, 14 Feb 2020 05:48:31 +0000 (+0900) Subject: revise apis for multi notification callback X-Git-Tag: submit/tizen/20200319.043412~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7f0d78ed5cd74ef32df188d74bcb3753bf84ba54;p=platform%2Fcore%2Fsystem%2Fmodes.git revise apis for multi notification callback --- diff --git a/client/mdsc_noti_mode.c b/client/mdsc_noti_mode.c index 62fadd3..87c58a7 100644 --- a/client/mdsc_noti_mode.c +++ b/client/mdsc_noti_mode.c @@ -15,52 +15,92 @@ */ #include "modes.h" +#include #include #include "mdsc.h" #include "common/dbus.h" -struct mdsc_noti_data_s { +typedef struct { modes_noti_fn cb; void *user_data; -}; +} mdsc_noti_data_s; static gulong mdsc_noti_signal_ID = 0; -static struct mdsc_noti_data_s mdsc_noti_data; +static GList *mdsc_noti_cb_list = NULL; -static void _on_changed_mode(mdsDbus *mdsc_dbus, const char *mode, int state, gpointer user_data) +static gint _compare_cb(gconstpointer a, gconstpointer b) { - //TODO:: should support multi callback - //RET_IF(NULL == user_data); + RETV_IF(NULL == a, 1); + RETV_IF(NULL == b, 1); + + const mdsc_noti_data_s *a_data = a; + const mdsc_noti_data_s *b_data = b; + if ((a_data->cb == b_data->cb) + && (a_data->user_data == b_data->user_data)) + return 0; + return -1; +} - mdsc_noti_data.cb(mode, state, mdsc_noti_data.user_data); +static void _on_changed_mode(mdsDbus *mdsc_dbus, const char *mode, int state, gpointer user_data) +{ + GList *it; + for (it = mdsc_noti_cb_list; it != NULL; it = g_list_next(it)) { + mdsc_noti_data_s *data = it->data; + if (data && data->cb) + data->cb(mode, state, data->user_data); + } } API int modes_subscribe_mode_changes(modes_h handle, modes_noti_fn cb, void *user_data) { - RETV_IF(0 != mdsc_noti_signal_ID, MODES_ERROR_ALREADY); RETV_IF(NULL == handle, MODES_ERROR_INVALID_PARAMETER); RETV_IF(NULL == handle->conn, MODES_ERROR_INVALID_PARAMETER); - mdsc_noti_data.cb = cb; - mdsc_noti_data.user_data = user_data; + mdsc_noti_data_s search_data = { cb, user_data }; + GList *found = g_list_find_custom(mdsc_noti_cb_list, &search_data, _compare_cb); + if (NULL != found) { + ERR("callback and user_data already exist in notification callback list"); + return MODES_ERROR_ALREADY; + } - mdsc_noti_signal_ID = g_signal_connect(handle->conn, - "changed-mode", - G_CALLBACK(_on_changed_mode), - NULL); + mdsc_noti_data_s *data = malloc(sizeof(mdsc_noti_data_s)); + if (NULL == data) { + ERR("malloc() Fail"); + return MODES_ERROR_SYSTEM; + } + + data->cb = cb; + data->user_data = user_data; + + if (NULL == mdsc_noti_cb_list) + mdsc_noti_signal_ID = g_signal_connect(handle->conn, + "changed-mode", + G_CALLBACK(_on_changed_mode), + NULL); + mdsc_noti_cb_list = g_list_append(mdsc_noti_cb_list, data); return MODES_ERROR_NONE; } -//TODO: multi callbacks -API void modes_unsubscribe_mode_changes(modes_h handle) +API void modes_unsubscribe_mode_changes(modes_h handle, modes_noti_fn cb, void *user_data) { RET_IF(0 == mdsc_noti_signal_ID); RET_IF(NULL == handle); RET_IF(NULL == handle->conn); - g_signal_handler_disconnect(handle->conn, mdsc_noti_signal_ID); - mdsc_noti_signal_ID = 0; - mdsc_noti_data.cb = NULL; - mdsc_noti_data.user_data = NULL; + mdsc_noti_data_s search = { cb, user_data }; + GList *found = g_list_find_custom(mdsc_noti_cb_list, &search, _compare_cb); + if (NULL == found) { + WARN("g_list_find_custom() Fail"); + return; + } + + mdsc_noti_data_s *data = found->data; + mdsc_noti_cb_list = g_list_remove(mdsc_noti_cb_list, found->data); + free(data); + if (NULL == mdsc_noti_cb_list) { + g_signal_handler_disconnect(handle->conn, mdsc_noti_signal_ID); + mdsc_noti_signal_ID = 0; + } + } diff --git a/include/modes.h b/include/modes.h index 24fb5b8..592075e 100644 --- a/include/modes.h +++ b/include/modes.h @@ -244,10 +244,13 @@ int modes_subscribe_mode_changes(modes_h handle, modes_noti_fn cb, void *user_da * @brief stop recognizing the changed of mode. * @details Removes a function to be called when the mode is changed. * @since_tizen 6.0 + + * @param[in] cb The callback function to stop invoking + * @param[in] user_data The user data to pass to the function * * @see modes_subscribe_mode_changes() */ -void modes_unsubscribe_mode_changes(modes_h handle); +void modes_unsubscribe_mode_changes(modes_h handle, modes_noti_fn cb, void *user_data); //TODO:it must be opaque type typedef struct { diff --git a/unittest/modes_test_noti.cpp b/unittest/modes_test_noti.cpp index f488def..fb7f738 100644 --- a/unittest/modes_test_noti.cpp +++ b/unittest/modes_test_noti.cpp @@ -39,14 +39,14 @@ protected: int ret = modes_undo_mode(handle, (const char*)data); EXPECT_EQ(MODES_ERROR_NONE, ret); - return G_SOURCE_REMOVE; + return G_SOURCE_REMOVE; } static int notiFunc(const char *modeName, int state, void *user_data) { char *requestMode = (char*)user_data; - std::cout << "Changed Mode : " << modeName << std::endl; + std::cout << "notiFunc Changed Mode : " << modeName << std::endl; EXPECT_EQ(requestMode, std::string(modeName)); std::cout << "state : " << state << std::endl; EXPECT_EQ(expectedState, state); @@ -60,7 +60,7 @@ protected: { char *requestMode = (char*)user_data; - std::cout << "Changed Mode : " << modeName << std::endl; + std::cout << "changeFn Changed Mode : " << modeName << std::endl; EXPECT_EQ(requestMode, std::string(modeName)); std::cout << "state : " << state << std::endl; @@ -69,14 +69,64 @@ protected: return MODES_ERROR_NONE; } + + static int notiMultiFunc1(const char *modeName, int state, void *user_data) + { + std::cout << "notiMultiFunc1 Changed Mode : " << modeName << std::endl; + std::cout << "state : " << state << std::endl; + + calledbit1 |= 0x1 << state; + + return MODES_ERROR_NONE; + } + + static int notiMultiFunc2(const char *modeName, int state, void *user_data) + { + std::cout << "notiMultiFunc2 Changed Mode : " << modeName << std::endl; + std::cout << "state : " << state << std::endl; + + calledbit2 |= 0x1 << state; + + return MODES_ERROR_NONE; + } + + static int notiMultiFunc3(const char *modeName, int state, void *user_data) + { + std::cout << "notiMultiFunc3 Changed Mode : " << modeName << std::endl; + std::cout << "state : " << state << std::endl; + + EXPECT_TRUE(NULL == user_data || notiTestMode == user_data); + + if (NULL == user_data) + calledbit3 |= 0x1 << state; + if (notiTestMode == user_data) + calledbit4 |= 0x1 << state; + + if (0x3 == calledbit3 && 0x3 == calledbit4) + g_main_loop_quit(loop); + + return MODES_ERROR_NONE; + } + + static modes_h handle; static int expectedState; static GMainLoop *loop; + static unsigned char calledbit1; + static unsigned char calledbit2; + static unsigned char calledbit3; + static unsigned char calledbit4; + static const char *notiTestMode; }; modes_h ClientNotiTest::handle = NULL; int ClientNotiTest::expectedState = 1; +unsigned char ClientNotiTest::calledbit1 = 0; +unsigned char ClientNotiTest::calledbit2 = 0; +unsigned char ClientNotiTest::calledbit3 = 0; +unsigned char ClientNotiTest::calledbit4 = 0; GMainLoop *ClientNotiTest::loop = NULL; +const char *ClientNotiTest::notiTestMode = "ex2"; TEST_F(ClientNotiTest, notiConnect) { @@ -92,7 +142,41 @@ TEST_F(ClientNotiTest, notiConnect) g_main_loop_run(loop); - modes_unsubscribe_mode_changes(handle); + modes_unsubscribe_mode_changes(handle, notiFunc, (void*)testMode); +} +TEST_F(ClientNotiTest, notiMultiCb) +{ + calledbit1 = 0; + calledbit2 = 0; + calledbit3 = 0; + + int ret = modes_subscribe_mode_changes(handle, notiMultiFunc1, NULL); + EXPECT_EQ(MODES_ERROR_NONE, ret); + + ret = modes_subscribe_mode_changes(handle, notiMultiFunc2, NULL); + EXPECT_EQ(MODES_ERROR_NONE, ret); + + ret = modes_subscribe_mode_changes(handle, notiMultiFunc3, (void*)notiTestMode); + EXPECT_EQ(MODES_ERROR_NONE, ret); + + ret = modes_subscribe_mode_changes(handle, notiMultiFunc3, NULL); + EXPECT_EQ(MODES_ERROR_NONE, ret); + + ret = modes_apply_mode(handle, notiTestMode); + EXPECT_EQ(MODES_ERROR_NONE, ret); + + g_timeout_add_seconds(1, undoTimeout, (void*)notiTestMode); + g_main_loop_run(loop); + + modes_unsubscribe_mode_changes(handle, notiMultiFunc1, NULL); + modes_unsubscribe_mode_changes(handle, notiMultiFunc2, NULL); + modes_unsubscribe_mode_changes(handle, notiMultiFunc3, NULL); + modes_unsubscribe_mode_changes(handle, notiMultiFunc3, (void*)notiTestMode); + + EXPECT_EQ(calledbit1, 1 << 0 | 1 << 1); + EXPECT_EQ(calledbit2, 1 << 0 | 1 << 1); + EXPECT_EQ(calledbit3, 1 << 0 | 1 << 1); + EXPECT_EQ(calledbit4, 1 << 0 | 1 << 1); } TEST_F(ClientNotiTest, essential) @@ -106,5 +190,5 @@ TEST_F(ClientNotiTest, essential) g_main_loop_run(loop); - modes_unsubscribe_mode_changes(handle); + modes_unsubscribe_mode_changes(handle, changeFn, (void*)testMode); }