add subscribe/unsubscribe changes API 49/236349/2
authorYoungjae Shin <yj99.shin@samsung.com>
Tue, 16 Jun 2020 10:55:53 +0000 (19:55 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Thu, 18 Jun 2020 02:42:44 +0000 (11:42 +0900)
Change-Id: I1d78c3aad2bc48702dc6ee70545860ee0bce7cec

include/system_settings.h
packaging/capi-system-system-settings.spec
src/sst_api.c
src/sst_vconf.c
src/sst_vconf.h

index 7fd1473..a97282f 100644 (file)
@@ -138,6 +138,9 @@ typedef enum {
  */
 typedef void (*system_settings_changed_cb)(system_settings_key_e key, void *user_data);
 
+
+typedef void* system_settings_cb_id;
+
 /**
  * @platform
  * @brief Sets the system settings value associated with the given key as an integer.
index 96519b9..26a5b6f 100644 (file)
@@ -1,7 +1,7 @@
 Name:       capi-system-system-settings
 Summary:    A System Settings library in Tizen Native API
-Version:    0.0.4
-Release:    5
+Version:    0.0.5
+Release:    0
 
 Group:      System/System Info
 License:    Apache-2.0
index 0a35146..a4bd2a4 100644 (file)
@@ -325,3 +325,58 @@ API int system_settings_remove_changed_cb(system_settings_key_e key, system_sett
 
        return SYSTEM_SETTINGS_ERROR_NONE;
 }
+
+int system_settings_subscribe_changes(system_settings_key_e key, system_settings_changed_cb callback, void *user_data, system_settings_cb_id *id)
+{
+       int ret;
+
+       RETV_IF(NULL == id, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == callback, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+
+       sst_interface *iface = NULL;
+       ret = sst_get_interface(key, &iface);
+       if (SYSTEM_SETTINGS_ERROR_NONE != ret) {
+               ERR("sst_get_interface(%d) Fail(%d)", key, ret);
+               return ret;
+       }
+
+       if (NULL == iface->vconf_key) {
+               ERR("NULL vconf_key of key(%d)", key);
+               return SYSTEM_SETTINGS_ERROR_NOT_SUPPORTED;
+       }
+
+       ret = sst_vconf_subscribe(iface, callback, user_data, id);
+       if (SYSTEM_SETTINGS_ERROR_NONE != ret) {
+               ERR("sst_vconf_subscribe() Fail(%d)", ret);
+               return ret;
+       }
+       return SYSTEM_SETTINGS_ERROR_NONE;
+}
+
+int system_settings_unsubscribe_changes(system_settings_key_e key, system_settings_cb_id id)
+{
+       int ret;
+
+       RETV_IF(NULL == id, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+
+       sst_interface *iface = NULL;
+       ret = sst_get_interface(key, &iface);
+       if (SYSTEM_SETTINGS_ERROR_NONE != ret) {
+               ERR("sst_get_interface(%d) Fail(%d)", key, ret);
+               return ret;
+       }
+
+       if (NULL == iface->vconf_key) {
+               ERR("NULL vconf_key of key(%d)", key);
+               return SYSTEM_SETTINGS_ERROR_NOT_SUPPORTED;
+       }
+
+       ret = sst_vconf_unsubscribe(iface, id);
+       if (SYSTEM_SETTINGS_ERROR_NONE != ret) {
+               ERR("sst_vconf_unsubscribe() Fail(%d)", ret);
+               return ret;
+       }
+       return SYSTEM_SETTINGS_ERROR_NONE;
+
+
+}
index 54f6a56..c9ca3ba 100644 (file)
@@ -25,8 +25,9 @@
 #include "sst_misc.h"
 #include "sst_interface.h"
 
-static GHashTable *sst_vconf_map_org = NULL;
+static GHashTable *sst_vconf_map_old = NULL;
 static GHashTable *sst_vconf_map = NULL;
+static GHashTable *sst_vconf_map_new = NULL;
 
 struct sst_vconf_info_s {
        system_settings_key_e key;
@@ -132,21 +133,80 @@ int sst_vconf_get_str_ally(const char *vconf_key, char **value)
        return SYSTEM_SETTINGS_ERROR_NONE;
 }
 
-static inline GHashTable* _map_erase(GHashTable *hash_table, const char *key)
+//Because of a lot of parameters, it is an inline function
+static inline int _subscribe(sst_interface *iface, system_settings_changed_cb cb, void *user_data, GHashTable **vconf_map, GList *list, vconf_callback_fn vconf_cb, system_settings_cb_id *id)
 {
-       g_hash_table_remove(hash_table, key);
-       if (0 == g_hash_table_size(hash_table)) {
-               g_hash_table_unref(hash_table);
-               return NULL;
+       GHashTable *map = *vconf_map;
+       struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
+       if (NULL == info) {
+               ERR("malloc() Fail(%d)", errno);
+               return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
        }
-       return hash_table;
+       info->key = iface->key;
+       info->cb = cb;
+       info->cb_data = user_data;
+
+       GList *new_list = g_list_append(list, info);
+       g_hash_table_replace(map, (char*)iface->vconf_key, new_list);
+
+       if (NULL == list) {
+               int ret = vconf_notify_key_changed(iface->vconf_key, vconf_cb, NULL);
+               if (VCONF_OK != ret) {
+                       ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
+                       new_list = g_list_remove(new_list, info);
+                       if (NULL == new_list) {
+                               g_hash_table_remove(map, iface->vconf_key);
+                               if (0 == g_hash_table_size(map)) {
+                                       g_hash_table_unref(map);
+                                       *vconf_map = NULL;
+                               }
+                       }
+                       free(info);
+                       return SYSTEM_SETTINGS_ERROR_IO_ERROR;
+               }
+       }
+
+       if (id)
+               *id = info;
+
+       return SYSTEM_SETTINGS_ERROR_NONE;
 }
 
-static void _callback_fn_org(keynode_t *node, void *user_data)
+static int _unsubscribe(const char *vconf_key, GList *found, GHashTable **vconf_map, vconf_callback_fn cb)
 {
-       RET_IF(NULL == sst_vconf_map_org);
+       GHashTable *map = *vconf_map;
+       GList *list = g_list_first(found);
+
+       if (1 == g_list_length(list)) {
+               int ret = vconf_ignore_key_changed(vconf_key, cb);
+               if (VCONF_OK != ret) {
+                       ERR("vconf_ignore_key_changed(%s) Fail", vconf_key);
+                       return SYSTEM_SETTINGS_ERROR_IO_ERROR;
+               }
+       }
+
+       list = g_list_remove_link(list, found);
+       if (list) {
+               g_hash_table_replace(map, (char*)vconf_key, list);
+       } else {
+               g_hash_table_remove(map, vconf_key);
+               if (0 == g_hash_table_size(map)) {
+                       g_hash_table_unref(map);
+                       *vconf_map = NULL;
+               }
+       }
 
-       GList *list = g_hash_table_lookup(sst_vconf_map_org, node->keyname);
+       free(found->data);
+       g_list_free(found);
+
+       return SYSTEM_SETTINGS_ERROR_NONE;
+}
+
+static void _callback_fn_old(keynode_t *node, void *user_data)
+{
+       RET_IF(NULL == sst_vconf_map_old);
+
+       GList *list = g_hash_table_lookup(sst_vconf_map_old, node->keyname);
        GList *it;
        for (it = list; it; it = it->next) {
                struct sst_vconf_info_s *info = it->data;
@@ -174,74 +234,33 @@ int sst_vconf_set_cb(sst_interface *iface, system_settings_changed_cb cb, void *
        RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
        RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
 
-       if (sst_vconf_map_org) {
-               list = g_hash_table_lookup(sst_vconf_map_org, iface->vconf_key);
+       if (sst_vconf_map_old) {
+               list = g_hash_table_lookup(sst_vconf_map_old, iface->vconf_key);
                GList *found = g_list_find_custom(list, GINT_TO_POINTER(iface->key), _compare_key);
                if (found) {
                        ERR("callback Already Exist");
                        return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
                }
        } else {
-               sst_vconf_map_org = g_hash_table_new(g_str_hash, g_str_equal);
-       }
-
-       struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
-       if (NULL == info) {
-               ERR("malloc() Fail(%d)", errno);
-               return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
-       }
-       info->key = iface->key;
-       info->cb = cb;
-       info->cb_data = user_data;
-
-       GList *new_list = g_list_append(list, info);
-       g_hash_table_replace(sst_vconf_map_org, (char*)iface->vconf_key, new_list);
-
-       if (NULL == list) {
-               int ret = vconf_notify_key_changed(iface->vconf_key, _callback_fn_org, NULL);
-               if (VCONF_OK != ret) {
-                       ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
-                       new_list = g_list_remove(new_list, info);
-                       if (NULL == new_list)
-                               sst_vconf_map_org = _map_erase(sst_vconf_map_org, iface->vconf_key);
-                       free(info);
-                       return SYSTEM_SETTINGS_ERROR_IO_ERROR;
-               }
+               sst_vconf_map_old = g_hash_table_new(g_str_hash, g_str_equal);
        }
 
-       return SYSTEM_SETTINGS_ERROR_NONE;
+       return _subscribe(iface, cb, user_data, &sst_vconf_map_old, list, _callback_fn_old, NULL);
 }
 
 int sst_vconf_unset_cb(sst_interface *iface)
 {
        RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
-       RETV_IF(NULL == sst_vconf_map_org, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == sst_vconf_map_old, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
 
-       GList *list = g_hash_table_lookup(sst_vconf_map_org, iface->vconf_key);
+       GList *list = g_hash_table_lookup(sst_vconf_map_old, iface->vconf_key);
        GList *found = g_list_find_custom(list, GINT_TO_POINTER(iface->key), _compare_key);
        if (NULL == found) {
                ERR("No callback");
                return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
        }
 
-       if (1 == g_list_length(list)) {
-               int ret = vconf_ignore_key_changed(iface->vconf_key, _callback_fn_org);
-               if (VCONF_OK != ret) {
-                       ERR("vconf_ignore_key_changed(%s) Fail", iface->vconf_key);
-                       return SYSTEM_SETTINGS_ERROR_IO_ERROR;
-               }
-       }
-
-       list = g_list_remove_link(list, found);
-       if (list)
-               g_hash_table_replace(sst_vconf_map_org, (char*)iface->vconf_key, list);
-       else
-               sst_vconf_map_org = _map_erase(sst_vconf_map_org, iface->vconf_key);
-
-       free(found->data);
-       g_list_free(found);
-
-       return SYSTEM_SETTINGS_ERROR_NONE;
+       return _unsubscribe(iface->vconf_key, found, &sst_vconf_map_old, _callback_fn_old);
 }
 
 static void _callback_fn(keynode_t *node, void *user_data)
@@ -288,31 +307,7 @@ int sst_vconf_add_multi_cb(sst_interface *iface, system_settings_changed_cb cb,
                sst_vconf_map = g_hash_table_new(g_str_hash, g_str_equal);
        }
 
-       struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
-       if (NULL == info) {
-               ERR("malloc() Fail(%d)", errno);
-               return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
-       }
-       info->key = iface->key;
-       info->cb = cb;
-       info->cb_data = user_data;
-
-       GList *new_list = g_list_append(list, info);
-       g_hash_table_replace(sst_vconf_map, (char*)iface->vconf_key, new_list);
-
-       if (NULL == list) {
-               int ret = vconf_notify_key_changed(iface->vconf_key, _callback_fn, NULL);
-               if (VCONF_OK != ret) {
-                       ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
-                       new_list = g_list_remove(new_list, info);
-                       if (NULL == new_list)
-                               sst_vconf_map = _map_erase(sst_vconf_map, iface->vconf_key);
-                       free(info);
-                       return SYSTEM_SETTINGS_ERROR_IO_ERROR;
-               }
-       }
-
-       return SYSTEM_SETTINGS_ERROR_NONE;
+       return _subscribe(iface, cb, user_data, &sst_vconf_map, list, _callback_fn, NULL);
 }
 
 int sst_vconf_del_multi_cb(sst_interface *iface, system_settings_changed_cb cb)
@@ -328,22 +323,50 @@ int sst_vconf_del_multi_cb(sst_interface *iface, system_settings_changed_cb cb)
                return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
        }
 
-       if (1 == g_list_length(list)) {
-               int ret = vconf_ignore_key_changed(iface->vconf_key, _callback_fn);
-               if (VCONF_OK != ret) {
-                       ERR("vconf_ignore_key_changed(%s) Fail", iface->vconf_key);
-                       return SYSTEM_SETTINGS_ERROR_IO_ERROR;
-               }
+       return _unsubscribe(iface->vconf_key, found, &sst_vconf_map, _callback_fn);
+}
+
+static void _callback_fn_new(keynode_t *node, void *user_data)
+{
+       RET_IF(NULL == sst_vconf_map_new);
+
+       GList *list = g_hash_table_lookup(sst_vconf_map_new, node->keyname);
+       GList *it;
+       for (it = list; it; it = it->next) {
+               struct sst_vconf_info_s *info = it->data;
+               if (info && info->cb)
+                       info->cb(info->key, info->cb_data);
        }
+}
 
-       list = g_list_remove_link(list, found);
-       if (list)
-               g_hash_table_replace(sst_vconf_map, (char*)iface->vconf_key, list);
-       else
-               sst_vconf_map = _map_erase(sst_vconf_map, iface->vconf_key);
+int sst_vconf_subscribe(sst_interface *iface, system_settings_changed_cb cb, void *user_data, system_settings_cb_id *id)
+{
+       GList *list = NULL;
 
-       free(found->data);
-       g_list_free(found);
+       RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
 
-       return SYSTEM_SETTINGS_ERROR_NONE;
+       if (sst_vconf_map_new) {
+               list = g_hash_table_lookup(sst_vconf_map_new, iface->vconf_key);
+       } else {
+               sst_vconf_map_new = g_hash_table_new(g_str_hash, g_str_equal);
+       }
+
+       return _subscribe(iface, cb, user_data, &sst_vconf_map_new, list, _callback_fn_new, id);
 }
+
+int sst_vconf_unsubscribe(sst_interface *iface, system_settings_cb_id id)
+{
+       RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == id, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == sst_vconf_map_new, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+
+       GList *list = g_hash_table_lookup(sst_vconf_map_new, iface->vconf_key);
+       GList *found = g_list_find(list, id);
+       if (NULL == found) {
+               ERR("No callback");
+               return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
+       }
+
+       return _unsubscribe(iface->vconf_key, found, &sst_vconf_map_new, _callback_fn_new);
+}
\ No newline at end of file
index e118f25..bb6de56 100644 (file)
@@ -32,3 +32,6 @@ int sst_vconf_unset_cb(sst_interface *iface);
 
 int sst_vconf_add_multi_cb(sst_interface *iface, system_settings_changed_cb cb, void *user_data);
 int sst_vconf_del_multi_cb(sst_interface *iface, system_settings_changed_cb cb);
+
+int sst_vconf_subscribe(sst_interface *iface, system_settings_changed_cb cb, void *user_data, system_settings_cb_id *id);
+int sst_vconf_unsubscribe(sst_interface *iface, system_settings_cb_id id);
\ No newline at end of file