2 * Copyright (c) 2015 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.
24 #include <glib/gstdio.h>
25 #include <bundle_internal.h>
29 #include <system_info.h>
33 #include "aul_rsc_mgr.h"
34 #include "aul_rsc_mgr_internal.h"
36 #define WEIGHT_SCREEN_DPI 10000
37 #define WEIGHT_SCREEN_DPI_RANGE 10000
38 #define WEIGHT_SCREEN_BPP 1000
39 #define WEIGHT_SCREEN_WIDTH_RANGE 100
40 #define WEIGHT_SCREEN_LARGE 10
41 #define WEIGHT_PLATFORM_VERSION 1000000
42 #define WEIGHT_LANGUAGE 100000
44 #define THRESHOLD_TO_CLEAN 50 /* app_resource_manager_trim_cache */
46 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
50 resource_data_t *data;
58 } resource_cache_context_t;
61 const char *bundle_attr_key;
62 unsigned int bundle_attr_value;
63 } resource_node_attr_t;
68 } resource_node_list_t;
73 NODE_ATTR_SCREEN_DPI_RANGE,
74 NODE_ATTR_SCREEN_WIDTH_RANGE,
75 NODE_ATTR_SCREEN_LARGE,
77 NODE_ATTR_PLATFORM_VER,
82 static resource_manager_t *resource_handle = NULL;
84 static resource_node_attr_t map[] = {
85 { RSC_NODE_ATTR_SCREEN_DPI, NODE_ATTR_SCREEN_DPI },
86 { RSC_NODE_ATTR_SCREEN_DPI_RANGE, NODE_ATTR_SCREEN_DPI_RANGE },
87 { RSC_NODE_ATTR_SCREEN_WIDTH_RANGE, NODE_ATTR_SCREEN_WIDTH_RANGE },
88 { RSC_NODE_ATTR_SCREEN_LARGE, NODE_ATTR_SCREEN_LARGE },
89 { RSC_NODE_ATTR_SCREEN_BPP, NODE_ATTR_SCREEN_BPP },
90 { RSC_NODE_ATTR_PLATFORM_VER, NODE_ATTR_PLATFORM_VER },
91 { RSC_NODE_ATTR_LANGUAGE, NODE_ATTR_LANGUAGE },
94 static GHashTable *attr_key = NULL;
95 static const char *res_path = NULL;
96 static char *cur_language = NULL;
97 static bool is_slice = FALSE;
99 static GHashTable *valid_path_list = NULL;
100 static GHashTable *supported_lang_list = NULL;
101 static GHashTable *id_list = NULL;
102 static GList *all_node_list = NULL;
103 static bundle *given_attr_list = NULL;
105 static gint __resource_manager_comp(gconstpointer a, gconstpointer b)
107 resource_group_t *rsc_group = (resource_group_t *) a;
109 return strcmp(rsc_group->type, b);
112 static gint __compare_path(gconstpointer a, gconstpointer b)
114 char tmp_path[MAX_PATH] = {0, };
115 resource_node_list_t *tmp_node_info = (resource_node_list_t *)a;
117 snprintf(tmp_path, MAX_PATH - 1, "%s%s", res_path, tmp_node_info->folder);
118 return strncmp(tmp_path, (char *)b, strlen(tmp_path));
121 static int __get_dpi(void)
127 bundle_get_str(given_attr_list, RSC_NODE_ATTR_SCREEN_DPI, &tmp);
129 LOGE("Failed to retrieve DPI");
135 system_info_get_platform_int("http://tizen.org/feature/screen.dpi", &dpi);
141 static int __get_screen_width(void)
143 int screen_width = 0;
147 bundle_get_str(given_attr_list, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE, &tmp);
149 LOGE("Failed to retrieve screen width");
152 screen_width = atoi(tmp);
154 system_info_get_platform_int("http://tizen.org/feature/screen.width", &screen_width);
159 static bool __get_screen_large(void)
161 bool screen_large = true;
165 bundle_get_str(given_attr_list, RSC_NODE_ATTR_SCREEN_LARGE, &tmp);
167 LOGE("Failed to retrieve screen large");
168 screen_large = false;
170 screen_large = atoi(tmp);
172 if (system_info_get_platform_bool("http://tizen.org/feature/screen.size.large", &screen_large) != SYSTEM_INFO_ERROR_NONE) {
173 LOGE("Failed to get info of screen.size.large");
174 screen_large = false;
181 static int __get_screen_bpp(void)
187 bundle_get_str(given_attr_list, RSC_NODE_ATTR_SCREEN_BPP, &tmp);
189 LOGE("Failed to retrieve screen bpp");
192 screen_bpp = atoi(tmp);
194 system_info_get_platform_int("http://tizen.org/feature/screen.bpp", &screen_bpp);
199 static char *__get_platform_version(void)
201 char *version = NULL;
203 bundle_get_str(given_attr_list, RSC_NODE_ATTR_PLATFORM_VER, &version);
205 system_info_get_platform_string("http://tizen.org/feature/platform.version", &version);
210 static void __bundle_iterator_get_valid_nodes(const char *key, const int type,
211 const bundle_keyval_t *kv, void *data)
213 unsigned int node_attr;
214 bool *invalid = (bool *) data;
215 bool ret_bool = true;
222 static int screen_dpi = -1;
223 static int screen_width = -1;
224 static int screen_size_large = -1;
225 static char *version = NULL;
226 static int screen_bpp = -1;
231 bundle_keyval_get_basic_val((bundle_keyval_t *) kv, (void**) &val, &size);
233 node_attr = (uintptr_t)g_hash_table_lookup(attr_key, key);
234 if (node_attr <= NODE_ATTR_MIN || node_attr >= NODE_ATTR_MAX) {
235 LOGE("INVALID_PARAMETER(0x%08x), node_attr(%d)",
236 AUL_RESOURCE_ERROR_INVALID_PARAMETER, node_attr);
242 case NODE_ATTR_SCREEN_DPI:
243 if (screen_dpi == -1)
244 screen_dpi = __get_dpi();
245 if (screen_dpi != atoi(val))
248 case NODE_ATTR_SCREEN_DPI_RANGE:
249 sscanf(val, "%ms %d %ms %d", &from, &min, &to, &max);
250 if (screen_dpi == -1)
251 screen_dpi = __get_dpi();
252 if (!(min <= screen_dpi && screen_dpi <= max))
259 case NODE_ATTR_SCREEN_WIDTH_RANGE:
260 sscanf(val, "%ms %d %ms %d", &from, &min, &to, &max);
261 if (screen_width == -1)
262 screen_width = __get_screen_width();
263 if (!(min <= screen_width && screen_width <= max))
270 case NODE_ATTR_SCREEN_LARGE:
271 if (!(strcmp(val, "true")))
275 if (screen_size_large == -1) {
276 ret_bool = __get_screen_large();
278 screen_size_large = 1;
280 screen_size_large = 0;
282 if (((bool)screen_size_large) != t_val)
285 case NODE_ATTR_SCREEN_BPP:
286 if (screen_bpp == -1)
287 screen_bpp = __get_screen_bpp();
288 if (screen_bpp != atoi(val))
291 case NODE_ATTR_PLATFORM_VER:
293 version = __get_platform_version();
294 if (strcmp(version, val))
297 case NODE_ATTR_LANGUAGE:
298 if (cur_language == NULL) {
299 cur_language = vconf_get_str(VCONFKEY_LANGSET);
300 if (cur_language == NULL)
303 if (cur_language && strncmp(cur_language, val, strlen(val)))
309 static void __bundle_iterator_get_best_node(const char *key, const char *val,
312 unsigned int node_attr;
313 unsigned int *weight = (unsigned int *)data;
315 node_attr = (uintptr_t)g_hash_table_lookup(attr_key, key);
316 if (node_attr <= NODE_ATTR_MIN || node_attr >= NODE_ATTR_MAX) {
317 LOGE("INVALID_PARAMETER(0x%08x), node_attr(%d)",
318 AUL_RESOURCE_ERROR_INVALID_PARAMETER, node_attr);
323 case NODE_ATTR_SCREEN_DPI:
324 *weight += WEIGHT_SCREEN_DPI;
326 case NODE_ATTR_SCREEN_DPI_RANGE:
327 *weight += WEIGHT_SCREEN_DPI_RANGE;
329 case NODE_ATTR_SCREEN_WIDTH_RANGE:
330 *weight += WEIGHT_SCREEN_WIDTH_RANGE;
332 case NODE_ATTR_SCREEN_LARGE:
333 *weight += WEIGHT_SCREEN_LARGE;
335 case NODE_ATTR_SCREEN_BPP:
336 *weight += WEIGHT_SCREEN_BPP;
338 case NODE_ATTR_PLATFORM_VER:
339 *weight += WEIGHT_PLATFORM_VERSION;
341 case NODE_ATTR_LANGUAGE:
342 *weight += WEIGHT_LANGUAGE;
347 static const char *__get_cache(aul_resource_e type,
350 unsigned int total_len = 0;
353 resource_cache_context_t *resource_cache = NULL;
355 if (is_slice == TRUE)
360 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
364 if (type < AUL_RESOURCE_TYPE_MIN || type > AUL_RESOURCE_TYPE_MAX) {
365 LOGW("(0x%08x), type(%d)",
366 AUL_RESOURCE_ERROR_INVALID_PARAMETER, type);
370 case AUL_RESOURCE_TYPE_IMAGE:
371 rsc_type = RSC_GROUP_TYPE_IMAGE;
373 case AUL_RESOURCE_TYPE_LAYOUT:
374 rsc_type = RSC_GROUP_TYPE_LAYOUT;
376 case AUL_RESOURCE_TYPE_SOUND:
377 rsc_type = RSC_GROUP_TYPE_SOUND;
379 case AUL_RESOURCE_TYPE_BIN:
380 rsc_type = RSC_GROUP_TYPE_BIN;
385 if (resource_handle->cache == NULL) {
386 LOGW("(0x%08x), hashtable",
387 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
390 total_len = (unsigned int)(strlen(rsc_type) + strlen(id) + 2);
391 key = (char *)calloc(1, total_len);
393 LOGE("OOM!, failed to create a resource_cache(0x%08x)",
394 AUL_RESOURCE_ERROR_OUT_OF_MEMORY);
395 free(resource_cache);
399 snprintf(key, total_len, "%s:%s", rsc_type, id);
400 LOGD("key : %s", key);
402 resource_cache = g_hash_table_lookup(resource_handle->cache, key);
404 if (resource_cache == NULL) {
405 LOGW("(0x%08x), find list resource_cache",
406 AUL_RESOURCE_ERROR_IO_ERROR);
410 resource_cache->hit_cnt++;
413 return resource_cache->output;
416 static gint __cache_hit_compare(gconstpointer a, gconstpointer b)
418 const resource_cache_context_t *lhs = (const resource_cache_context_t *) a;
419 const resource_cache_context_t *rhs = (const resource_cache_context_t *) b;
421 return lhs->hit_cnt - rhs->hit_cnt;
424 static gboolean __cache_remove(gpointer key, gpointer value, gpointer user_data)
426 resource_cache_context_t *c = (resource_cache_context_t *) (value);
438 static void __trim_cache(void)
440 GList *values = g_hash_table_get_values(resource_handle->cache);
441 values = g_list_sort(values, __cache_hit_compare);
444 GList *iter_list = values;
445 while (iter_list != NULL) {
446 if (i >= (THRESHOLD_TO_CLEAN / 2))
449 resource_cache_context_t *c =
450 (resource_cache_context_t *) (iter_list->data);
452 iter_list = g_list_next(iter_list);
457 g_hash_table_foreach_remove(resource_handle->cache, __cache_remove, NULL);
461 static void __put_cache(aul_resource_e type, const char *id,
464 unsigned int total_len = 0;
467 resource_cache_context_t *resource_cache;
469 if (is_slice == TRUE)
472 /* To remove chache from the low frequency of use. */
474 LOGE("INVALID_PARAMETER(0x%08x), fname",
475 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
480 LOGE("INVALID_PARAMETER(0x%08x), id",
481 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
485 if (type < AUL_RESOURCE_TYPE_MIN || type > AUL_RESOURCE_TYPE_MAX) {
486 LOGE("INVALID_PARAMETER(0x%08x), type(%d)",
487 AUL_RESOURCE_ERROR_INVALID_PARAMETER, type);
491 case AUL_RESOURCE_TYPE_IMAGE:
492 rsc_type = RSC_GROUP_TYPE_IMAGE;
494 case AUL_RESOURCE_TYPE_LAYOUT:
495 rsc_type = RSC_GROUP_TYPE_LAYOUT;
497 case AUL_RESOURCE_TYPE_SOUND:
498 rsc_type = RSC_GROUP_TYPE_SOUND;
500 case AUL_RESOURCE_TYPE_BIN:
501 rsc_type = RSC_GROUP_TYPE_BIN;
506 if (g_hash_table_size(resource_handle->cache) > THRESHOLD_TO_CLEAN)
509 resource_cache = (resource_cache_context_t *)calloc(1,
510 sizeof(resource_cache_context_t));
511 if (resource_cache == NULL) {
512 LOGE("failed to create a resource_group(0x%08x)",
513 AUL_RESOURCE_ERROR_OUT_OF_MEMORY);
517 total_len = (unsigned int)(strlen(rsc_type) + strlen(id) + 2);
518 key = (char *)calloc(1, total_len);
520 LOGE("failed to create a resource_cache(0x%08x)",
521 AUL_RESOURCE_ERROR_OUT_OF_MEMORY);
522 free(resource_cache);
526 snprintf(key, total_len, "%s:%s", rsc_type, id);
527 LOGD("key : %s", key);
529 resource_cache->output = strdup(val);
530 resource_cache->hit_cnt = 0;
531 resource_cache->remove = false;
533 g_hash_table_insert(resource_handle->cache, key, resource_cache);
536 static resource_group_t *__find_group(resource_data_t *data,
539 resource_group_t *rsc_group = NULL;
543 LOGE("INVALID_PARAMETER(0x%08x), resource_data_t",
544 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
548 if (type < AUL_RESOURCE_TYPE_MIN || type > AUL_RESOURCE_TYPE_MAX) {
549 LOGE("INVALID_PARAMETER(0x%08x), type(%d)",
550 AUL_RESOURCE_ERROR_INVALID_PARAMETER, type);
554 case AUL_RESOURCE_TYPE_IMAGE:
555 rsc_type = RSC_GROUP_TYPE_IMAGE;
557 case AUL_RESOURCE_TYPE_LAYOUT:
558 rsc_type = RSC_GROUP_TYPE_LAYOUT;
560 case AUL_RESOURCE_TYPE_SOUND:
561 rsc_type = RSC_GROUP_TYPE_SOUND;
563 case AUL_RESOURCE_TYPE_BIN:
564 rsc_type = RSC_GROUP_TYPE_BIN;
569 GList* found = g_list_find_custom(data->group_list, rsc_type,
570 __resource_manager_comp);
572 LOGE("IO_ERROR(0x%08x), find list resource_group %s",
573 AUL_RESOURCE_ERROR_IO_ERROR, rsc_type);
577 rsc_group = (resource_group_t *) (found->data);
582 static GList *__get_valid_nodes(resource_group_t *group,
586 GList *valid_list = NULL;
587 resource_node_t *valid_node = NULL;
588 resource_node_t *rsc_node = NULL;
590 if (group->node_list == NULL) {
591 LOGE("INVALID_PARAMETER(0x%08x), resource_group",
592 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
596 list = g_list_first(group->node_list);
598 char path_buf[MAX_PATH] = { 0, };
600 bool invalid = false;
601 rsc_node = (resource_node_t *) list->data;
603 snprintf(path_buf, MAX_PATH - 1, "%s%s/%s", res_path,
604 rsc_node->folder, id);
605 if (access(path_buf, R_OK) == 0) {
606 bundle_foreach(rsc_node->attr, __bundle_iterator_get_valid_nodes,
610 valid_node = (resource_node_t *) list->data;
611 valid_list = g_list_append(valid_list, valid_node);
615 list = g_list_next(list);
621 static resource_node_t *__get_best_node(GList *nodes)
623 unsigned int weight_tmp = 0;
624 resource_node_t *best_node = NULL;
628 LOGE("INVALID_PARAMETER(0x%08x), resource_node lists",
629 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
633 list = g_list_first(nodes);
635 while (list != NULL) {
636 unsigned int weight = 0;
637 resource_node_t *res_node = (resource_node_t *) (list->data);
639 bundle_iterate(res_node->attr, __bundle_iterator_get_best_node, &weight);
640 if (weight > weight_tmp) {
641 best_node = res_node;
644 list = g_list_next(list);
650 static int __open(resource_manager_t **handle)
652 int retval = AUL_RESOURCE_ERROR_NONE;
653 resource_manager_t *rsc_manager = NULL;
654 char buf[MAX_PATH] = { 0, };
656 rsc_manager = (resource_manager_t *) calloc(1, sizeof(resource_manager_t));
658 LOGE("failed to create a resource_manager(0x%08x)",
659 AUL_RESOURCE_ERROR_OUT_OF_MEMORY);
660 return AUL_RESOURCE_ERROR_OUT_OF_MEMORY;
663 snprintf(buf, MAX_PATH - 1, "%sres.xml", res_path);
664 retval = _resource_open(buf, &(rsc_manager->data));
666 LOGE("IO_ERROR(0x%08x), failed to get db for resource manager",
667 AUL_RESOURCE_ERROR_IO_ERROR);
669 return AUL_RESOURCE_ERROR_IO_ERROR;
672 rsc_manager->cache = g_hash_table_new(g_str_hash, g_str_equal);
673 *handle = rsc_manager;
675 return AUL_RESOURCE_ERROR_NONE;
678 static void __invalidate_cache()
680 if (resource_handle != NULL) {
681 if (resource_handle->cache != NULL) {
685 g_hash_table_iter_init(&iter, resource_handle->cache);
686 while (g_hash_table_iter_next(&iter, &key, &value)) {
688 resource_cache_context_t *c = (resource_cache_context_t *) value;
692 g_hash_table_remove_all(resource_handle->cache);
701 static int __close(resource_manager_t *handle)
703 if (handle == NULL) {
704 LOGE("INVALID_PARAMETER(0x%08x), resource_manager",
705 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
706 return AUL_RESOURCE_ERROR_INVALID_PARAMETER;
709 __invalidate_cache();
710 if (handle->cache != NULL)
711 g_hash_table_destroy(handle->cache);
713 if (handle->data != NULL)
714 _resource_close(handle->data);
718 return AUL_RESOURCE_ERROR_NONE;
721 static void __vconf_cb(keynode_t *key, void *data)
725 val = vconf_keynode_get_str(key);
726 if (val && cur_language && !strcmp(val, cur_language))
729 __invalidate_cache();
732 static const char *_get_app_resource_path(const char *rsc_folder_path)
734 if (is_slice == FALSE)
735 return aul_get_app_resource_path();
737 if (rsc_folder_path == NULL)
740 return rsc_folder_path;
743 static void path_callback(char *path)
745 char orig_path[PATH_MAX] = {0, };
746 char *path_ptr = NULL;
748 GList *tmp_list = g_list_find_custom(all_node_list, path, __compare_path);
750 resource_node_list_t *tmp_node_info = NULL;
751 if (tmp_list == NULL)
752 g_hash_table_add(valid_path_list, strdup(path));
754 tmp_node_info = (resource_node_list_t *)tmp_list->data;
755 path_len = strlen(path);
756 if (path_len >= PATH_MAX) {
757 LOGE("path[%s] is too long", path);
760 strncpy(orig_path, path, sizeof(orig_path) - path_len - 1);
761 path_ptr = &orig_path[strlen(res_path) + strlen(tmp_node_info->folder)];
762 g_hash_table_insert(id_list, strdup(path_ptr), strdup(tmp_node_info->type));
766 static void __scan_dir(const char *path, void (*func)(char *))
768 struct dirent **items;
771 char abs_path[PATH_MAX] = {0, };
772 char cwd[MAX_PATH] = {0, };
775 if (chdir(path) < 0) {
776 LOGE("failed to chdir[%s]", path);
780 tmp = getcwd(cwd, MAX_PATH - 1);
782 LOGE("failed to get cwd");
785 nitems = scandir("./", &items, NULL, alphasort);
787 for (i = 0; i < nitems; i++) {
788 if (items[i]->d_name[0] == '.')
791 snprintf(abs_path, sizeof(abs_path), "%s/%s", cwd, items[i]->d_name);
793 if (g_lstat(abs_path, &fstat) != 0) {
794 LOGE("failed to retrieve info[%s]", abs_path);
797 if ((fstat.st_mode & S_IFDIR) == S_IFDIR)
798 __scan_dir(abs_path, path_callback);
805 static aul_resource_e __get_resource_type(char *type)
810 if (strcmp(type, RSC_GROUP_TYPE_IMAGE) == 0)
811 return AUL_RESOURCE_TYPE_IMAGE;
812 else if (strcmp(type, RSC_GROUP_TYPE_LAYOUT) == 0)
813 return AUL_RESOURCE_TYPE_LAYOUT;
814 else if (strcmp(type, RSC_GROUP_TYPE_SOUND) == 0)
815 return AUL_RESOURCE_TYPE_SOUND;
816 else if (strcmp(type, RSC_GROUP_TYPE_BIN) == 0)
817 return AUL_RESOURCE_TYPE_BIN;
822 static int __set_valid_filelist(bundle *b)
824 if (b == NULL || supported_lang_list == NULL) {
825 LOGE("INVALID_PARAMETER(0x%08x), bundle",
826 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
827 return AUL_RESOURCE_ERROR_INVALID_PARAMETER;
830 int retval = AUL_RESOURCE_ERROR_NONE;
832 GHashTableIter id_list_iter;
833 GHashTableIter lang_list_iter;
834 gpointer id_key, lang_key, id_type;
835 aul_resource_e rsc_type = AUL_RESOURCE_TYPE_MIN;
838 g_hash_table_iter_init(&id_list_iter, id_list);
840 while (g_hash_table_iter_next(&id_list_iter, &id_key, &id_type)) {
841 rsc_type = __get_resource_type((char *)id_type);
842 if (rsc_type == -1) {
843 LOGE("failed to get resource type[%s]", (char *)id_type);
844 return AUL_RESOURCE_ERROR_IO_ERROR;
847 g_hash_table_iter_init(&lang_list_iter, supported_lang_list);
848 while (g_hash_table_iter_next(&lang_list_iter, &lang_key, NULL)) {
849 cur_language = strdup(lang_key);
850 if (cur_language == NULL) {
851 LOGE("failed to strdup");
852 return AUL_RESOURCE_ERROR_OUT_OF_MEMORY;
855 retval = aul_resource_manager_get(rsc_type, id_key, &path);
856 if (retval == AUL_RESOURCE_ERROR_NONE)
857 g_hash_table_add(valid_path_list, path);
859 LOGE("failed to get value with given type[%d], key[%s]", rsc_type, (const char *)id_key);
867 return AUL_RESOURCE_ERROR_NONE;
870 static int __make_list(void)
872 resource_group_t *tmp_group = NULL;
873 resource_node_t *tmp_node = NULL;
874 resource_node_list_t *tmp_node_struct = NULL;
875 char *group_type = NULL;
876 char folder[MAX_PATH] = {0 ,};
877 char *node_lang = NULL;
878 GList *group_list = NULL;
879 GList *node_list = NULL;
883 /* make node folder list */
884 group_list = resource_handle->data->group_list;
885 if (group_list == NULL)
886 return AUL_RESOURCE_ERROR_IO_ERROR;
888 while (group_list != NULL) {
889 tmp_group = (resource_group_t *)group_list->data;
890 if (tmp_group == NULL)
891 return AUL_RESOURCE_ERROR_IO_ERROR;
893 group_type = tmp_group->type;
894 node_list = tmp_group->node_list;
895 memset(folder, '\0', MAX_PATH);
896 snprintf(folder, MAX_PATH - 1, "%s/", tmp_group->folder);
898 /* make struct and put it into all node list */
899 tmp_node_struct = (resource_node_list_t *)calloc(1, sizeof(resource_node_list_t));
900 if (tmp_node_struct == NULL) {
901 LOGE("calloc failed");
902 return AUL_RESOURCE_ERROR_OUT_OF_MEMORY;
905 tmp_node_struct->folder = strdup(folder);
906 tmp_node_struct->type = strdup(group_type);
907 all_node_list = g_list_append(all_node_list, tmp_node_struct);
909 while (node_list != NULL) {
910 tmp_node = (resource_node_t *)node_list->data;
911 if (tmp_node == NULL)
912 return AUL_RESOURCE_ERROR_IO_ERROR;
914 /* retrieve language value from each node */
917 return AUL_RESOURCE_ERROR_IO_ERROR;
918 bundle_get_str(b, RSC_NODE_ATTR_LANGUAGE, &node_lang);
919 if (node_lang != NULL)
920 g_hash_table_add(supported_lang_list, strdup(node_lang));
922 memset(folder, '\0', MAX_PATH);
923 snprintf(folder, MAX_PATH - 1, "%s/", tmp_node->folder);
925 /* make struct and put it into all node list */
926 tmp_node_struct = (resource_node_list_t *)calloc(1, sizeof(resource_node_list_t));
927 if (tmp_node_struct == NULL) {
928 LOGE("calloc failed");
929 return AUL_RESOURCE_ERROR_OUT_OF_MEMORY;
932 tmp_node_struct->folder = strdup(folder);
933 tmp_node_struct->type = strdup(group_type);
934 all_node_list = g_list_prepend(all_node_list, tmp_node_struct);
936 node_list = g_list_next(node_list);
938 group_list = g_list_next(group_list);
941 __scan_dir(res_path, path_callback);
943 /* add language which is not existed to find default resources */
944 g_hash_table_add(supported_lang_list, strdup("NoLang"));
945 return AUL_RESOURCE_ERROR_NONE;
948 static void __free_str(gpointer data)
953 char *char_data = (char *)data;
958 static int __init(const char *rsc_folder_path, bundle *b)
960 if (rsc_folder_path != NULL && b != NULL)
965 if (resource_handle != NULL)
966 return AUL_RESOURCE_ERROR_NONE;
968 int retval = AUL_RESOURCE_ERROR_NONE;
970 res_path = _get_app_resource_path(rsc_folder_path);
971 if (res_path == NULL) {
972 LOGE("IO_ERROR(0x%08x), failed to get resource path",
973 AUL_RESOURCE_ERROR_IO_ERROR);
974 return AUL_RESOURCE_ERROR_IO_ERROR;
977 retval = __open(&resource_handle);
978 if (retval != AUL_RESOURCE_ERROR_NONE) {
979 LOGE("IO_ERROR(0x%08x), failed to get resource_handle(%d)",
980 AUL_RESOURCE_ERROR_IO_ERROR, retval);
981 return AUL_RESOURCE_ERROR_IO_ERROR;
984 if (attr_key == NULL) {
985 attr_key = g_hash_table_new(g_str_hash, g_str_equal);
987 if (attr_key == NULL)
988 return AUL_RESOURCE_ERROR_OUT_OF_MEMORY;
991 for (i = 0; i < ARRAY_SIZE(map); i++) {
992 g_hash_table_insert(attr_key, (char *)map[i].bundle_attr_key,
993 (gpointer)((uintptr_t)(map[i].bundle_attr_value)));
997 if (is_slice == FALSE) {
998 int r = vconf_notify_key_changed(VCONFKEY_LANGSET, __vconf_cb, NULL);
1001 LOGE("IO_ERROR(0x%08x), failed to register vconf(%d)",
1002 AUL_RESOURCE_ERROR_IO_ERROR, r);
1003 return AUL_RESOURCE_ERROR_IO_ERROR;
1007 if (id_list == NULL)
1008 id_list = g_hash_table_new_full(g_str_hash, g_str_equal, __free_str, __free_str);
1010 if (supported_lang_list == NULL)
1011 supported_lang_list = g_hash_table_new_full(g_str_hash, g_str_equal, __free_str, NULL);
1013 if (valid_path_list == NULL)
1014 valid_path_list = g_hash_table_new_full(g_str_hash, g_str_equal, __free_str, NULL);
1016 retval = __make_list();
1018 LOGE("Failed to initialize filelist");
1019 return AUL_RESOURCE_ERROR_IO_ERROR;
1022 retval = __set_valid_filelist(b);
1024 LOGE("Failed to get valid filelist");
1025 return AUL_RESOURCE_ERROR_IO_ERROR;
1030 return AUL_RESOURCE_ERROR_NONE;
1033 API int aul_resource_manager_init(void)
1035 return __init(NULL, NULL);
1038 API int aul_resource_manager_init_slice(const char *rsc_folder_path, bundle *b)
1040 if (rsc_folder_path == NULL || b == NULL)
1041 return AUL_RESOURCE_ERROR_INVALID_PARAMETER;
1043 return __init(rsc_folder_path, b);
1047 API int aul_resource_manager_get_path_list(GHashTable **list)
1049 if (is_slice == FALSE)
1050 return AUL_RESOURCE_ERROR_IO_ERROR;
1052 if (valid_path_list != NULL)
1053 *list = valid_path_list;
1055 return AUL_RESOURCE_ERROR_IO_ERROR;
1057 return AUL_RESOURCE_ERROR_NONE;
1060 static bool __verify_current_language(void)
1064 lang = vconf_get_str(VCONFKEY_LANGSET);
1068 if (cur_language && !strcmp(lang, cur_language)) {
1078 API int aul_resource_manager_get(aul_resource_e type, const char *id, char **path)
1080 int retval = AUL_RESOURCE_ERROR_NONE;
1081 char *put_fname = NULL;
1082 const char *cached_path = NULL;
1084 resource_group_t *resource_group = NULL;
1085 resource_node_t *resource_node = NULL;
1090 LOGE("INVALID_PARAMETER(0x%08x), resource_data_t",
1091 AUL_RESOURCE_ERROR_INVALID_PARAMETER);
1092 return AUL_RESOURCE_ERROR_INVALID_PARAMETER;
1095 if (type < AUL_RESOURCE_TYPE_MIN || type > AUL_RESOURCE_TYPE_MAX) {
1096 LOGE("INVALID_PARAMETER(0x%08x), type(%d)",
1097 AUL_RESOURCE_ERROR_INVALID_PARAMETER, type);
1098 return AUL_RESOURCE_ERROR_INVALID_PARAMETER;
1101 if (is_slice == FALSE) {
1102 if (resource_handle == NULL) {
1103 retval = aul_resource_manager_init();
1104 if (retval != AUL_RESOURCE_ERROR_NONE)
1108 if (__verify_current_language()) {
1109 /* To get fname from cache */
1110 cached_path = __get_cache(type, id);
1111 if (cached_path != NULL) {
1112 *path = strdup(cached_path);
1113 return AUL_RESOURCE_ERROR_NONE;
1116 __invalidate_cache();
1120 if (resource_handle == NULL)
1121 return AUL_RESOURCE_ERROR_IO_ERROR;
1123 resource_group = __find_group(resource_handle->data, type);
1124 if (resource_group == NULL) {
1125 LOGE("IO_ERROR(0x%08x), failed to get resource_group",
1126 AUL_RESOURCE_ERROR_IO_ERROR);
1127 retval = AUL_RESOURCE_ERROR_IO_ERROR;
1131 list = __get_valid_nodes(resource_group, id);
1133 retval = AUL_RESOURCE_ERROR_IO_ERROR;
1137 resource_node = __get_best_node(list);
1138 if (resource_node == NULL) {
1139 retval = AUL_RESOURCE_ERROR_IO_ERROR;
1142 unsigned int total_len = (unsigned int)(strlen(res_path)
1143 + strlen(resource_node->folder)
1145 put_fname = (char *) calloc(1, total_len);
1149 return AUL_RESOURCE_ERROR_OUT_OF_MEMORY;
1151 snprintf(put_fname, total_len, "%s%s/%s", res_path,
1152 resource_node->folder, id);
1153 *path = strdup(put_fname);
1156 __put_cache(type, id, put_fname);
1163 if (put_fname == NULL && resource_group != NULL) {
1164 char path_buf[MAX_PATH] = { 0, };
1165 char group_path_buf[MAX_PATH] = { 0, };
1167 snprintf(path_buf, MAX_PATH - 1, "%s%s/%s", res_path,
1168 resource_group->folder, id);
1169 snprintf(group_path_buf, MAX_PATH - 1, "%s/%s", resource_group->folder, id);
1171 list = g_list_first(resource_group->node_list);
1173 resource_node = (resource_node_t *) list->data;
1174 if (strncmp(group_path_buf, resource_node->folder, strlen(resource_node->folder)) == 0) {
1176 return AUL_RESOURCE_ERROR_IO_ERROR;
1178 list = g_list_next(list);
1181 if (access(path_buf, R_OK) == 0) {
1182 __put_cache(type, id, path_buf);
1183 *path = strdup(path_buf);
1184 retval = AUL_RESOURCE_ERROR_NONE;
1188 if (put_fname != NULL)
1194 static void __free_node_folder_list(gpointer data)
1196 resource_node_list_t *node_data = (resource_node_list_t *)data;
1197 if (node_data == NULL)
1200 if (node_data->folder != NULL) {
1201 free(node_data->folder);
1202 node_data->folder = NULL;
1205 if (node_data->type != NULL) {
1206 free(node_data->type);
1207 node_data->type = NULL;
1213 API int aul_resource_manager_release(void)
1215 if (resource_handle != NULL) {
1216 __close(resource_handle);
1217 resource_handle = NULL;
1220 if (attr_key != NULL) {
1221 g_hash_table_destroy(attr_key);
1227 cur_language = NULL;
1230 if (is_slice == FALSE)
1231 vconf_ignore_key_changed(VCONFKEY_LANGSET, __vconf_cb);
1233 if (valid_path_list != NULL) {
1234 g_hash_table_destroy(valid_path_list);
1235 valid_path_list = NULL;
1238 if (supported_lang_list != NULL) {
1239 g_hash_table_destroy(supported_lang_list);
1240 supported_lang_list = NULL;
1243 if (id_list != NULL) {
1244 g_hash_table_destroy(id_list);
1248 if (all_node_list != NULL) {
1249 g_list_free_full(all_node_list, __free_node_folder_list);
1250 all_node_list = NULL;
1253 return AUL_RESOURCE_ERROR_NONE;