2 * Copyright (c) 2011-2020 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include "sst_vconf.h"
26 #include "sst_interface.h"
28 static GHashTable *sst_vconf_map_old = NULL;
29 static GHashTable *sst_vconf_map = NULL;
30 static GHashTable *sst_vconf_map_new = NULL;
32 static pthread_mutex_t sst_vconf_map_lock = PTHREAD_MUTEX_INITIALIZER;
33 static pthread_mutex_t sst_vconf_map_new_lock = PTHREAD_MUTEX_INITIALIZER;
35 struct sst_vconf_info_s {
36 system_settings_key_e key;
37 system_settings_changed_cb cb;
41 int sst_vconf_set_int(sst_interface *iface, int val)
43 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
44 RETV_IF(NULL == iface->vconf_key, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
46 if (VCONF_OK != vconf_set_int(iface->vconf_key, val)) {
47 ERR("vconf_set_int(%s, %d) Fail", iface->vconf_key, val);
48 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
51 return SYSTEM_SETTINGS_ERROR_NONE;
54 int sst_vconf_set_bool(sst_interface *iface, bool val)
56 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
57 RETV_IF(NULL == iface->vconf_key, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
59 if (VCONF_OK != vconf_set_bool(iface->vconf_key, val)) {
60 ERR("vconf_set_bool(%s, %d) Fail", iface->vconf_key, val);
61 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
64 return SYSTEM_SETTINGS_ERROR_NONE;
67 int sst_vconf_set_str(sst_interface *iface, const char *val)
69 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
70 RETV_IF(NULL == iface->vconf_key, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
72 if (VCONF_OK != vconf_set_str(iface->vconf_key, val)) {
73 ERR("vconf_set_str(%s, %s) Fail", iface->vconf_key, val);
74 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
77 return SYSTEM_SETTINGS_ERROR_NONE;
80 int sst_vconf_get_int(sst_interface *iface, int *val)
82 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
83 RETV_IF(NULL == iface->vconf_key, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
86 if (VCONF_OK != vconf_get_int(iface->vconf_key, &result)) {
87 ERR("vconf_get_int(%s) Fail", iface->vconf_key);
88 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
93 return SYSTEM_SETTINGS_ERROR_NONE;
96 int sst_vconf_get_bool(sst_interface *iface, bool *val)
98 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
99 RETV_IF(NULL == iface->vconf_key, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
102 if (VCONF_OK != vconf_get_bool(iface->vconf_key, &result)) {
103 ERR("vconf_get_bool(%s) Fail", iface->vconf_key);
104 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
107 *val = result ? true : false;
109 return SYSTEM_SETTINGS_ERROR_NONE;
112 int sst_vconf_get_str(sst_interface *iface, char **val)
114 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
115 RETV_IF(NULL == iface->vconf_key, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
117 char *result = vconf_get_str(iface->vconf_key);
118 if (NULL == result) {
119 ERR("vconf_get_str(%s) Fail(NULL)", iface->vconf_key);
120 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
124 return SYSTEM_SETTINGS_ERROR_NONE;
127 int sst_vconf_get_str_ally(const char *vconf_key, char **value)
129 char *str_value = vconf_get_str(vconf_key);
130 if (NULL == str_value) {
131 ERR("vconf_get_str(%s) Fail(NULL)", vconf_key);
132 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
136 return SYSTEM_SETTINGS_ERROR_NONE;
139 //Because of a lot of parameters, it is an inline function
140 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)
142 GHashTable *map = *vconf_map;
143 struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
145 ERR("malloc() Fail(%d)", errno);
146 return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
148 info->key = iface->key;
150 info->cb_data = user_data;
152 GList *new_list = g_list_append(list, info);
153 g_hash_table_replace(map, (char*)iface->vconf_key, new_list);
156 int ret = vconf_notify_key_changed(iface->vconf_key, vconf_cb, NULL);
157 if (VCONF_OK != ret) {
158 ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
159 new_list = g_list_remove(new_list, info);
160 if (NULL == new_list) {
161 g_hash_table_remove(map, iface->vconf_key);
162 if (0 == g_hash_table_size(map)) {
163 g_hash_table_unref(map);
168 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
175 return SYSTEM_SETTINGS_ERROR_NONE;
178 static int _unsubscribe(const char *vconf_key, GList *found, GHashTable **vconf_map, vconf_callback_fn cb)
180 GHashTable *map = *vconf_map;
181 GList *list = g_list_first(found);
183 if (1 == g_list_length(list)) {
184 int ret = vconf_ignore_key_changed(vconf_key, cb);
185 if (VCONF_OK != ret) {
186 ERR("vconf_ignore_key_changed(%s) Fail", vconf_key);
187 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
191 list = g_list_remove_link(list, found);
193 g_hash_table_replace(map, (char*)vconf_key, list);
195 g_hash_table_remove(map, vconf_key);
196 if (0 == g_hash_table_size(map)) {
197 g_hash_table_unref(map);
205 return SYSTEM_SETTINGS_ERROR_NONE;
208 static void _callback_fn_old(keynode_t *node, void *user_data)
210 RET_IF(NULL == sst_vconf_map_old);
212 GList *list = g_hash_table_lookup(sst_vconf_map_old, node->keyname);
214 for (it = list; it; it = it->next) {
215 struct sst_vconf_info_s *info = it->data;
216 if (info && info->cb)
217 info->cb(info->key, info->cb_data);
221 static gint _compare_key(gconstpointer a, gconstpointer b)
223 const struct sst_vconf_info_s *info = a;
225 RETV_IF(NULL == a, 1);
227 if (info->key == GPOINTER_TO_INT(b))
233 int sst_vconf_set_cb(sst_interface *iface, system_settings_changed_cb cb, void *user_data)
237 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
238 RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
240 if (sst_vconf_map_old) {
241 list = g_hash_table_lookup(sst_vconf_map_old, iface->vconf_key);
242 GList *found = g_list_find_custom(list, GINT_TO_POINTER(iface->key), _compare_key);
244 ERR("callback Already Exist");
245 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
248 sst_vconf_map_old = g_hash_table_new(g_str_hash, g_str_equal);
251 return _subscribe(iface, cb, user_data, &sst_vconf_map_old, list, _callback_fn_old, NULL);
254 int sst_vconf_unset_cb(sst_interface *iface)
256 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
257 RETV_IF(NULL == sst_vconf_map_old, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
259 GList *list = g_hash_table_lookup(sst_vconf_map_old, iface->vconf_key);
260 GList *found = g_list_find_custom(list, GINT_TO_POINTER(iface->key), _compare_key);
263 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
266 return _unsubscribe(iface->vconf_key, found, &sst_vconf_map_old, _callback_fn_old);
269 static void _callback_fn(keynode_t *node, void *user_data)
271 RET_IF(NULL == sst_vconf_map);
273 GList *list = g_hash_table_lookup(sst_vconf_map, node->keyname);
275 for (it = list; it; it = it->next) {
276 struct sst_vconf_info_s *info = it->data;
277 if (info && info->cb)
278 info->cb(info->key, info->cb_data);
282 static gint _compare_cb(gconstpointer a, gconstpointer b)
284 const struct sst_vconf_info_s *info = a;
286 RETV_IF(NULL == a, 1);
287 RETV_IF(NULL == b, 1);
295 int sst_vconf_add_multi_cb(sst_interface *iface, system_settings_changed_cb cb, void *user_data)
300 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
301 RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
303 pthread_mutex_lock(&sst_vconf_map_lock);
305 list = g_hash_table_lookup(sst_vconf_map, iface->vconf_key);
306 GList *found = g_list_find_custom(list, cb, _compare_cb);
308 ERR("callback Already Exist");
309 pthread_mutex_unlock(&sst_vconf_map_lock);
310 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
313 sst_vconf_map = g_hash_table_new(g_str_hash, g_str_equal);
316 ret = _subscribe(iface, cb, user_data, &sst_vconf_map, list, _callback_fn, NULL);
317 pthread_mutex_unlock(&sst_vconf_map_lock);
321 int sst_vconf_del_multi_cb(sst_interface *iface, system_settings_changed_cb cb)
323 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
324 RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
325 RETV_IF(NULL == sst_vconf_map, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
327 pthread_mutex_lock(&sst_vconf_map_lock);
328 GList *list = g_hash_table_lookup(sst_vconf_map, iface->vconf_key);
329 GList *found = g_list_find_custom(list, cb, _compare_cb);
333 pthread_mutex_unlock(&sst_vconf_map_lock);
334 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
337 ret = _unsubscribe(iface->vconf_key, found, &sst_vconf_map, _callback_fn);
338 pthread_mutex_unlock(&sst_vconf_map_lock);
342 static void _callback_fn_new(keynode_t *node, void *user_data)
344 RET_IF(NULL == sst_vconf_map_new);
346 GList *list = g_hash_table_lookup(sst_vconf_map_new, node->keyname);
348 for (it = list; it; it = it->next) {
349 struct sst_vconf_info_s *info = it->data;
350 if (info && info->cb)
351 info->cb(info->key, info->cb_data);
355 int sst_vconf_subscribe(sst_interface *iface, system_settings_changed_cb cb, void *user_data, system_settings_cb_id *id)
360 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
361 RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
363 pthread_mutex_lock(&sst_vconf_map_new_lock);
364 if (sst_vconf_map_new) {
365 list = g_hash_table_lookup(sst_vconf_map_new, iface->vconf_key);
367 sst_vconf_map_new = g_hash_table_new(g_str_hash, g_str_equal);
370 ret = _subscribe(iface, cb, user_data, &sst_vconf_map_new, list, _callback_fn_new, id);
371 pthread_mutex_unlock(&sst_vconf_map_new_lock);
375 int sst_vconf_unsubscribe(sst_interface *iface, system_settings_cb_id id)
377 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
378 RETV_IF(NULL == id, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
379 RETV_IF(NULL == sst_vconf_map_new, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
381 pthread_mutex_lock(&sst_vconf_map_new_lock);
382 GList *list = g_hash_table_lookup(sst_vconf_map_new, iface->vconf_key);
383 GList *found = g_list_find(list, id);
387 pthread_mutex_unlock(&sst_vconf_map_new_lock);
388 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
391 ret = _unsubscribe(iface->vconf_key, found, &sst_vconf_map_new, _callback_fn_new);
392 pthread_mutex_unlock(&sst_vconf_map_new_lock);