Fix memory issue about the value read by GDBM
[platform/core/api/system-info.git] / src / system_info.c
index 24776e8..b580ed4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-
-#include <vconf.h>
-#include <dlog.h>
+#include <ctype.h>
+#include <gdbm.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <glib.h>
 
 #include <system_info.h>
 #include <system_info_private.h>
 #include <sys/utsname.h>
 
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "CAPI_SYSTEM_INFO"
+#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
+#define KEY_PREFIX "http://"
 
 #define SYSTEM_INFO_MAX -1
+#define KEY_MAX 256
+#define STR_MAX 256
 
-typedef struct {
-       system_info_key_e key;
-       system_info_data_type_e data_type;
-       system_info_get_value_cb get_value_cb;
-} system_info_s;
-
-typedef system_info_s * system_info_h;
-
-system_info_s system_info_table[] = {
-
-{
-        /**< The model of the device */
-       SYSTEM_INFO_KEY_MODEL,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_model
-},
-
-{
-        /**< The version of the Tizen supported by the platform */
-       SYSTEM_INFO_KEY_TIZEN_VERSION,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_tizen_version
-},
-
-{
-       /**< Indicates whether the device supports Bluetooth */
-       SYSTEM_INFO_KEY_BLUETOOTH_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_bluetooth_supported
-},
-
-{
-       /**< The number of cameras in the device */
-       SYSTEM_INFO_KEY_CAMERA_COUNT,
-       SYSTEM_INFO_DATA_TYPE_INT,
-       system_info_get_camera_count
-},
-
-{
-       /**< Indicates whether the device supports FM radio */
-       SYSTEM_INFO_KEY_FMRADIO_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_fmradio_supported
-},
-
-{
-       /**< Indicates whether the device supports GPS */
-       SYSTEM_INFO_KEY_GPS_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_gps_supported
-},
-
-{
-       /**< The type of the keyboard */
-       SYSTEM_INFO_KEY_KEYBOARD_TYPE,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_keyboard_type
-},
-
-{
-       /**< The maximum number of concurrent touch points supported
-       in the device */
-       SYSTEM_INFO_KEY_MULTI_POINT_TOUCH_COUNT,
-       SYSTEM_INFO_DATA_TYPE_INT,
-       system_info_get_multi_point_touch_count
-},
-
-{
-       /**< The supported network type */
-       SYSTEM_INFO_KEY_NETWORK_TYPE,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_network_type
-},
-
-{
-       /**< Indicates whether the device supports NFC */
-       SYSTEM_INFO_KEY_NFC_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_nfc_supported
-},
-
-{
-       /**< The supported version of the OpenGL ES */
-       SYSTEM_INFO_KEY_OPENGLES_VERSION,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_opengles_version
-},
-
-{
-       /**< The number of bits per pixel */
-       SYSTEM_INFO_KEY_SCREEN_BITS_PER_PIXEL,
-       SYSTEM_INFO_DATA_TYPE_INT,
-       system_info_get_screen_bits_per_pixel
-},
-
-{
-       /**< The height of the screen in pixels */
-       SYSTEM_INFO_KEY_SCREEN_HEIGHT,
-       SYSTEM_INFO_DATA_TYPE_INT,
-       system_info_get_screen_height
-},
-
-{
-       /**< The width of the screen in pixels */
-       SYSTEM_INFO_KEY_SCREEN_WIDTH,
-       SYSTEM_INFO_DATA_TYPE_INT,
-       system_info_get_screen_width
-},
-
-{
-       /**< Indicates whether the device supports TV-out */
-       SYSTEM_INFO_KEY_TVOUT_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_tvout_supported
-},
-
-{
-        /**< Indicates whether the device supports Wi-Fi */
-       SYSTEM_INFO_KEY_WIFI_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_wifi_supported
-},
-
-{
-        /**< The unique ID to identify GSM, and UMTS mobile devices */
-       SYSTEM_INFO_KEY_MOBILE_DEVICE_ID,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_mobile_device_id
-},
-
-{
-       /**< The sales code of the CSC */
-       SYSTEM_INFO_KEY_CSC_SALES_CODE,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_csc_sales_code
-},
-
-{
-       /**< The Name of the Platform */
-       SYSTEM_INFO_KEY_PLATFORM_NAME,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_platform_name
-},
-
-{
-       /**< The Name of the Tizen version */
-       SYSTEM_INFO_KEY_TIZEN_VERSION_NAME,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_tizen_version_name
-},
-
-{
-       /**< Indicates whether the device supports HAPTIC */
-       SYSTEM_INFO_KEY_HAPTIC_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_haptic_supproted
-},
+#define GDBM_CACHE_SIZE 10 /* GDBM default == 100 */
 
-{
-       /**< Indicates whether the device supports HAPTIC */
-       SYSTEM_INFO_KEY_WIFI_DIRECT_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_wifi_direct_supported
-},
+extern const struct runtime runtime[LANG_MAX];
 
-{
-       /**< The height of the screen DPI */
-       SYSTEM_INFO_KEY_SCREEN_DPI,
-       SYSTEM_INFO_DATA_TYPE_INT,
-       system_info_get_screen_DPI
-},
-
-{
-       /**< The Device unique ID to identify */
-       SYSTEM_INFO_KEY_DEVICE_UUID,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_device_uuid
-},
-
-{
-       /**< Indicates whether the device supports GPS */
-       SYSTEM_INFO_KEY_CPS_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_cps_supported
-},
-
-{
-       /**< Indicates whether the device supports GPS */
-       SYSTEM_INFO_KEY_WPS_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_wps_supported
-},
-
-{
-       /**< Indicates whether the device supports USB host */
-       SYSTEM_INFO_KEY_USB_HOST_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_usb_host_supported
-},
-
-{
-       /**< Indicates whether the device supports USB accessory */
-       SYSTEM_INFO_KEY_USB_ACCESSORY_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_usb_accessory_supported
-},
-
-{
-       /**< The CORE CPU architecture of model */
-       SYSTEM_INFO_KEY_CORE_CPU_ARCH,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_core_cpu_arch
-},
-
-{
-       /**< The CORE FPU architecture of model */
-       SYSTEM_INFO_KEY_CORE_FPU_ARCH,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_core_fpu_arch
-},
+GHashTable *hashtable = NULL;
+static pthread_mutex_t fmutex = PTHREAD_MUTEX_INITIALIZER;
 
-{
-       /**< Indicates whether the device supports front camera */
-       SYSTEM_INFO_KEY_FRONT_CAMERA_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_front_camera_supported
-},
-
-{
-       /**< Indicates whether the device supports front camera auto focus */
-       SYSTEM_INFO_KEY_FRONT_CAMERA_AF_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_front_camera_af_supported
-},
-
-{
-       /**< Indicates whether the device supports front camera flash */
-       SYSTEM_INFO_KEY_FRONT_CAMERA_FLASH_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_front_camera_flash_supported
-},
-
-{
-       /**< Indicates whether the device supports back camera */
-       SYSTEM_INFO_KEY_BACK_CAMERA_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_back_camera_supported
-},
-
-{
-       /**< Indicates whether the device supports back camera auto focus */
-       SYSTEM_INFO_KEY_BACK_CAMERA_AF_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_back_camera_af_supported
-},
-
-{
-       /**< Indicates whether the device supports back camera flash */
-       SYSTEM_INFO_KEY_BACK_CAMERA_FLASH_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_back_camera_flash_supported
-},
-
-{
-       /**< Indicates whether the device supports HDMI */
-       SYSTEM_INFO_KEY_HDMI_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_hdmi_supported
-},
-
-{
-       /**< Indicates whether the device supports RCA */
-       SYSTEM_INFO_KEY_RCA_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_rca_supported
-},
-
-{
-       /**< Indicates whether the device supports SIP VOIP */
-       SYSTEM_INFO_KEY_SIP_VOIP_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_sip_voip_supported
-},
-
-{
-       /**< Indicates whether the device supports Microphone */
-       SYSTEM_INFO_KEY_MICROPHONE_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_microphone_supported
-},
-
-{
-       /**< Indicates whether the device supports stt */
-       SYSTEM_INFO_KEY_SPEECH_RECOGNITION_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_speech_recognition_supported
-},
-
-{
-       /**< Indicates whether the device supports barometer sensor */
-       SYSTEM_INFO_KEY_BAROMETER_SENSOR_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_barometer_sensor_supported
-},
-
-{
-       /**< The supported texture format of the OpenGL ES */
-       SYSTEM_INFO_KEY_OPENGLES_TEXTURE_FORMAT,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_opengles_texture_format
-},
-
-{
-       /**< The CORE CPU frequency of model */
-       SYSTEM_INFO_KEY_CORE_CPU_FREQ,
-       SYSTEM_INFO_DATA_TYPE_DOUBLE,
-       system_info_get_core_cpu_freq
-},
-
-{
-       /**< The height of the physical screen size in millimeters */
-       SYSTEM_INFO_KEY_PHYSICAL_SCREEN_HEIGHT,
-       SYSTEM_INFO_DATA_TYPE_INT,
-       system_info_get_physical_screen_height
-},
-
-{
-       /**< The width of the physical screen size in millimeters */
-       SYSTEM_INFO_KEY_PHYSICAL_SCREEN_WIDTH,
-       SYSTEM_INFO_DATA_TYPE_INT,
-       system_info_get_physical_screen_width
-},
-
-{
-       /**< The build string of the platform binary */
-       SYSTEM_INFO_KEY_BUILD_STRING,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_build_string
-},
-
-{
-       /**< The build date of the platform binary */
-       SYSTEM_INFO_KEY_BUILD_DATE,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_build_date
-},
-
-{
-       /**< The build time of the platform binary */
-       SYSTEM_INFO_KEY_BUILD_TIME,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_build_time
-},
-
-{
-       /**< The manufacturer of the device */
-       SYSTEM_INFO_KEY_MANUFACTURER,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_manufacturer
-},
-
-{
-       /**< The method of interface with CP */
-       SYSTEM_INFO_KEY_CP_INTERFACE,
-       SYSTEM_INFO_DATA_TYPE_STRING,
-       system_info_get_cp_interface
-},
-
-{
-       /**< Indicates whether the device supports MMS */
-       SYSTEM_INFO_KEY_MMS_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_mms_supported
-},
-
-{
-       /**< Indicates whether the device supports SMS */
-       SYSTEM_INFO_KEY_SMS_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_sms_supported
-},
-
-{
-       /**< Indicates whether the device supports CBS */
-       SYSTEM_INFO_KEY_CBS_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_cbs_supported
-},
-
-{
-       /**< Indicates whether the device supports nfc-reserved push */
-       SYSTEM_INFO_KEY_NFC_RESERVED_PUSH_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_nfc_reserved_push_supported
-},
-
-{
-       /**< Indicates whether the device supports tethering */
-       SYSTEM_INFO_KEY_TETHERING_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_tethering_supported
-},
-
-{
-       /**< Indicates whether the device supports tts */
-       SYSTEM_INFO_KEY_SPEECH_SYNTHESIS_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_speech_synthesis_supported
-},
-
-{
-       /**< Indicates whether the device supports graphics hardware acceleration */
-       SYSTEM_INFO_KEY_GRAPHICS_HWACCEL_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_graphics_hwaccel_supported
-},
-
-{
-       /**< Indicates whether the device supports auto rotation feature */
-       SYSTEM_INFO_KEY_FEATURE_AUTO_ROTATION_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_feature_auto_rotation_supported
-},
+enum tag_type {
+       TAG_TYPE_PLATFORM,
+       TAG_TYPE_CUSTOM,
+};
 
+//LCOV_EXCL_START : not supported feature
+API int system_info_get_value_int(system_info_key_e key, int *value)
 {
-       /**< Indicates whether the device supports pinch zoom feature */
-       SYSTEM_INFO_KEY_FEATURE_PINCH_ZOOM_SUPPORTED,
-       SYSTEM_INFO_DATA_TYPE_BOOL,
-       system_info_get_feature_pinch_zoom_supported
-},
+       return SYSTEM_INFO_ERROR_NOT_SUPPORTED;
+}
 
+API int system_info_get_value_bool(system_info_key_e key, bool *value)
 {
-       SYSTEM_INFO_MAX, -1, NULL
+       return SYSTEM_INFO_ERROR_NOT_SUPPORTED;
 }
 
-};
-
-static system_info_mode_type_e system_info_system_info_model_type;
-static int system_info_initialized;
-
-int system_info_get_system_info_initialized(void)
+API int system_info_get_value_double(system_info_key_e key, double *value)
 {
-       return system_info_initialized;
+       return SYSTEM_INFO_ERROR_NOT_SUPPORTED;
 }
 
-void system_info_set_system_info_initialized(int value)
+API int system_info_get_value_string(system_info_key_e key, char **value)
 {
-       system_info_initialized = value;
+       return SYSTEM_INFO_ERROR_NOT_SUPPORTED;
 }
+//LCOV_EXCL_STOP
 
-system_info_mode_type_e system_info_get_system_info_model_type(void)
+static void destroy_key_value(gpointer data)
 {
-       return system_info_system_info_model_type;
+       free(data);
 }
 
-int system_info_init(void)
+static int db_get_value(enum tag_type tag, const char *key,
+               const char *type, char *value, size_t len)
 {
-       struct utsname device_name;
-       extern char *strcasestr(const char *s, const char *find);
+       char key_internal[KEY_MAX];
+       GDBM_FILE db = NULL;
+       datum d_key;
+       datum d_data;
+       int ret;
+       char *tag_s;
+       int cache_size = GDBM_CACHE_SIZE;
+       char *temp;
+
+       if (!key || !type || !value)
+               return SYSTEM_INFO_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       switch (tag) {
+       case TAG_TYPE_PLATFORM:
+               tag_s = TAG_TYPE_PLATFORM_STR;
+               break;
+       case TAG_TYPE_CUSTOM:
+               tag_s = TAG_TYPE_CUSTOM_STR;
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       int error = uname(&device_name);
+       if (strstr(key, KEY_PREFIX) == key)
+               snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", key, type, tag_s);
+       else
+               snprintf(key_internal, sizeof(key_internal), "%s%s:%s:%s", KEY_PREFIX, key, type, tag_s);
 
-       if (error != 0) {
-               LOGE("uname returns error!!!");
-               return SYSTEM_INFO_ERROR_IO_ERROR;
+       pthread_mutex_lock(&fmutex);
+       if (!hashtable) {
+               hashtable = g_hash_table_new_full(g_str_hash, g_str_equal, destroy_key_value, destroy_key_value);
        } else {
-               if (strcasestr(device_name.machine, "emulated"))
-                               system_info_system_info_model_type = SYSTEM_INFO_MODEL_TYPE_EMULATOR;
-               else
-               system_info_system_info_model_type = SYSTEM_INFO_MODEL_TYPE_TARGET;
-
-               system_info_set_system_info_initialized(1);
-       }
-       return SYSTEM_INFO_ERROR_NONE;
-}
-
-static int system_info_get(system_info_key_e key, system_info_h *system_info)
-{
-       int index = 0;
-       int ret_val;
-
-       if (0 == system_info_get_system_info_initialized()) {
-               ret_val = system_info_init();
-               if (ret_val) {
-                       LOGE("system information initialize fail!!!");
-                       return ret_val;
+               temp = (char *)g_hash_table_lookup(hashtable, key_internal);
+               if (temp) {
+                       snprintf(value, len, "%s", temp);
+                       pthread_mutex_unlock(&fmutex);
+                       return SYSTEM_INFO_ERROR_NONE;
                }
        }
 
-       while (system_info_table[index].key != SYSTEM_INFO_MAX) {
-               if (system_info_table[index].key == key) {
-                       *system_info = &system_info_table[index];
-                       return 0;
-               }
-
-               index++;
+       db = gdbm_open(SYSTEM_INFO_DB_PATH, 0, GDBM_READER, S_IRUSR | S_IRGRP | S_IROTH, NULL);
+       if (!db) {
+               _E("Failed to open db (%d, %s)", gdbm_errno, gdbm_strerror(gdbm_errno)); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
+               return SYSTEM_INFO_ERROR_IO_ERROR; //LCOV_EXCL_LINE
        }
 
-       return -1;
-}
+       ret = gdbm_setopt(db, GDBM_CACHESIZE, &cache_size, sizeof(cache_size));
+       if (ret < 0)
+               _E("Failed to set cache size to (%d) (ret:%d)", cache_size, gdbm_errno); //LCOV_EXCL_LINE
 
-int system_info_get_value(system_info_key_e key, system_info_data_type_e data_type, void **value)
-{
-       system_info_h system_info;
-       system_info_get_value_cb system_info_getter;
+       d_key.dptr = key_internal;
+       d_key.dsize = strlen(key_internal) + 1;
 
-       if (value == NULL) {
-               LOGE("INVALID_PARAMETER(0x%08x) : invalid output param", SYSTEM_INFO_ERROR_INVALID_PARAMETER);
-               return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
+       d_data = gdbm_fetch(db, d_key);
+       if (!d_data.dptr) {
+               _E("Failed to find key (%s, %s)", key, type);
+               ret = SYSTEM_INFO_ERROR_INVALID_PARAMETER;
+               goto out;
        }
 
-       if (system_info_get(key, &system_info)) {
-               LOGE("INVALID_PARAMETER(0x%08x) : invalid key", SYSTEM_INFO_ERROR_INVALID_PARAMETER);
-               return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
+       if (len <= d_data.dsize) {
+               _E("Buffer size is smaller than DB value size. It can be cut");
+               d_data.dsize = len - 1;
        }
 
-       if (system_info->data_type != data_type) {
-               LOGE("INVALID_PARAMETER(0x%08x) : invalid data type", SYSTEM_INFO_ERROR_INVALID_PARAMETER);
-               return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
-       }
+       memcpy(value, d_data.dptr, d_data.dsize);
+       value[d_data.dsize] = '\0';
+       free(d_data.dptr);
+       ret = SYSTEM_INFO_ERROR_NONE;
+
+       g_hash_table_insert(hashtable, strdup(key_internal), strdup(value));
+out:
+       if (db)
+               gdbm_close(db);
+       pthread_mutex_unlock(&fmutex);
+       return ret;
+}
 
-       system_info_getter = system_info->get_value_cb;
+struct sysinfo_type {
+       system_info_type_e type_e;
+       const char *type_str;
+} info_type[] = {
+       { SYSTEM_INFO_BOOL,   BOOL_TYPE },
+       { SYSTEM_INFO_INT,    INT_TYPE  },
+       { SYSTEM_INFO_DOUBLE, DBL_TYPE  },
+       { SYSTEM_INFO_STRING, STR_TYPE  },
+};
 
-       if (system_info_getter == NULL) {
-               LOGE("IO_ERROR(0x%08x) : failed to call getter for the system information", SYSTEM_INFO_ERROR_IO_ERROR);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
+static int system_info_get_type(enum tag_type tag, const char *key,
+               system_info_type_e *type)
+{
+       char key_internal[KEY_MAX];
+       GDBM_FILE db = NULL;
+       datum d_key;
+       datum d_data;
+       int ret, i;
+       char *tag_s;
+       int cache_size = GDBM_CACHE_SIZE;
+       char *temp;
+
+       if (!key || !type)
+               return SYSTEM_INFO_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       switch (tag) {
+       case TAG_TYPE_PLATFORM:
+               tag_s = TAG_TYPE_PLATFORM_STR;
+               break;
+       case TAG_TYPE_CUSTOM:
+               tag_s = TAG_TYPE_CUSTOM_STR;
+               break;
+       default:
+               return -EINVAL;
        }
 
-       return system_info_getter(key, system_info->data_type, value);
-}
-
-int system_info_get_value_int(system_info_key_e key, int *value)
-{
-       return system_info_get_value(key, SYSTEM_INFO_DATA_TYPE_INT, (void **)value);
-}
+       pthread_mutex_lock(&fmutex);
+       if (!hashtable) {
+               hashtable = g_hash_table_new_full(g_str_hash, g_str_equal, destroy_key_value, destroy_key_value);
+       } else {
+               for (i = 0 ; i < ARRAY_SIZE(info_type); i++) {
+                       if (strstr(key, KEY_PREFIX) == key)
+                               snprintf(key_internal, sizeof(key_internal),
+                                               "%s:%s:%s", key, info_type[i].type_str, tag_s);
+                       else
+                               snprintf(key_internal, sizeof(key_internal),
+                                               "%s%s:%s:%s", KEY_PREFIX, key, info_type[i].type_str, tag_s);
+                       temp = g_hash_table_lookup(hashtable, key_internal);
+                       if (!temp)
+                               continue;
+
+                       *type = info_type[i].type_e;
+                       pthread_mutex_unlock(&fmutex);
+                       return SYSTEM_INFO_ERROR_NONE;
+               }
+       }
 
-int system_info_get_value_bool(system_info_key_e key, bool *value)
-{
-       return system_info_get_value(key, SYSTEM_INFO_DATA_TYPE_BOOL, (void **)value);
-}
+       db = gdbm_open(SYSTEM_INFO_DB_PATH, 0, GDBM_READER, S_IRUSR | S_IRGRP | S_IROTH, NULL);
+       if (!db) {
+               _E("Failed to open db (%d, %s)", gdbm_errno, gdbm_strerror(gdbm_errno)); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
+               return SYSTEM_INFO_ERROR_IO_ERROR; //LCOV_EXCL_LINE
+       }
 
-int system_info_get_value_double(system_info_key_e key, double *value)
-{
-       return system_info_get_value(key, SYSTEM_INFO_DATA_TYPE_DOUBLE, (void **)value);
-}
+       ret = gdbm_setopt(db, GDBM_CACHESIZE, &cache_size, sizeof(cache_size));
+       if (ret < 0)
+               _E("Failed to set cache size to (%d) (ret:%d)", cache_size, gdbm_errno); //LCOV_EXCL_LINE
 
-int system_info_get_value_string(system_info_key_e key, char **value)
-{
-       return system_info_get_value(key, SYSTEM_INFO_DATA_TYPE_STRING, (void **)value);
-}
+       for (i = 0 ; i < ARRAY_SIZE(info_type); i++) {
+               if (strstr(key, KEY_PREFIX) == key)
+                       snprintf(key_internal, sizeof(key_internal),
+                                       "%s:%s:%s", key, info_type[i].type_str, tag_s);
+               else
+                       snprintf(key_internal, sizeof(key_internal),
+                                       "%s%s:%s:%s", KEY_PREFIX, key, info_type[i].type_str, tag_s);
 
-int system_info_get_external_bool(const char *key, bool *value)
-{
-       char vconfkey[MAXBUFSIZE] = {0,};
+               d_key.dptr = key_internal;
+               d_key.dsize = strlen(key_internal) + 1;
 
-       snprintf(vconfkey, strlen(EXTERNAL_VCONF_PREFIX)+strlen(key)+1, "%s%s", EXTERNAL_VCONF_PREFIX, key);
+               d_data = gdbm_fetch(db, d_key);
+               if (d_data.dptr) {
+                       *type = info_type[i].type_e;
+                       ret = SYSTEM_INFO_ERROR_NONE;
 
-       if (system_info_vconf_get_value_bool(vconfkey, value)) {
-               LOGE("key : %s, failed get bool value", key);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
+                       g_hash_table_insert(hashtable, strndup(key_internal, d_key.dsize),
+                                       strndup(d_data.dptr, d_data.dsize));
+                       free(d_data.dptr);
+                       goto out;
+               }
        }
 
-       return SYSTEM_INFO_ERROR_NONE;
-}
-
-int system_info_get_external_int(const char *key, int *value)
-{
-       char vconfkey[MAXBUFSIZE] = {0,};
-
-       snprintf(vconfkey, strlen(EXTERNAL_VCONF_PREFIX)+strlen(key)+1, "%s%s", EXTERNAL_VCONF_PREFIX, key);
-
-       if (system_info_vconf_get_value_int(vconfkey, value)) {
-               LOGE("key : %s, failed get int value", key);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
-       }
+       if (tag == TAG_TYPE_PLATFORM)
+               ret = system_info_get_type_file(key, type);
+       else
+               ret = SYSTEM_INFO_ERROR_INVALID_PARAMETER;
 
-       return SYSTEM_INFO_ERROR_NONE;
+out:
+       if (db)
+               gdbm_close(db);
+       pthread_mutex_unlock(&fmutex);
+       return ret;
 }
 
-int system_info_get_external_double(const char *key, double *value)
+static int system_info_get_bool(enum tag_type tag, const char *key, bool *value)
 {
-       char vconfkey[MAXBUFSIZE] = {0,};
-
-       snprintf(vconfkey, strlen(EXTERNAL_VCONF_PREFIX)+strlen(key)+1, "%s%s", EXTERNAL_VCONF_PREFIX, key);
+       int ret;
+       char val[16];
+       char *valp;
+       size_t len;
+       const char *runtime_type;
+       int rt;
+
+       if (!key || !value)
+               return SYSTEM_INFO_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       ret = db_get_value(tag, key, BOOL_TYPE, val, sizeof(val));
+       if (ret == SYSTEM_INFO_ERROR_NONE) {
+               runtime_type = getenv("RUNTIME_TYPE");
+               if (runtime_type) {
+                       for (rt = 0; rt < LANG_MAX; rt++) {
+                               if (!runtime[rt].runtime_type)
+                                       break;
+                               if (!strncmp(runtime_type, runtime[rt].runtime_type, RT_PREFIX)) {
+                                       *value = val[runtime[rt].lang] == 'T' ? true : false;
+                                       return SYSTEM_INFO_ERROR_NONE;
+                               }
+                       }
+                       _I("Unknown RUNTIME_TYPE, return default value");
+               }
 
-       if (system_info_vconf_get_value_double(vconfkey, value)) {
-               LOGE("key : %s, failed get double value", key);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
+               *value = val[runtime[DEFAULT].lang] == 'T' ? true : false;
+               return SYSTEM_INFO_ERROR_NONE;
        }
 
-       return SYSTEM_INFO_ERROR_NONE;
-}
-
-int system_info_get_external_string(const char *key, char **value)
-{
-       char vconfkey[MAXBUFSIZE] = {0,};
+       if (tag == TAG_TYPE_CUSTOM) {
+               ret = external_get_value(TAG_TYPE_CUSTOM_STR, key, BOOL_TYPE, &valp);
+               if (ret == SYSTEM_INFO_ERROR_NONE) {
+                       snprintf(val, sizeof(val), "%s", valp); //LCOV_EXCL_LINE
+                       free(valp); //LCOV_EXCL_LINE
 
-       snprintf(vconfkey, strlen(EXTERNAL_VCONF_PREFIX)+strlen(key)+1, "%s%s", EXTERNAL_VCONF_PREFIX, key);
+                       len = strlen(val) + 0;
+                       if (!strncmp(val, "true", len) || !strncmp(val, "TRUE", len))
+                               *value = true;
+                       else
+                               *value = false;
 
-       if (system_info_vconf_get_value_string(vconfkey, value)) {
-               LOGE("key : %s, failed get string value", key);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
+                       return SYSTEM_INFO_ERROR_NONE;
+               }
        }
 
-       return SYSTEM_INFO_ERROR_NONE;
+       _E("Invalid key (%s), type:bool", key);
+
+       return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
 }
 
-int system_info_get_platform_bool(const char *key, bool *value)
+static int system_info_get_int(enum tag_type tag, const char *key, int *value)
 {
        int ret;
-       bool *supported;
-       char *string = NULL;
-
-       supported = (bool *)value;
-
-       if (access(CONFIG_FILE_PATH, R_OK)) {
-               LOGE("cannot find file %s!!!", CONFIG_FILE_PATH);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
+       char val[128];
+       char *valp;
+
+       if (!key || !value)
+               return SYSTEM_INFO_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       ret = db_get_value(tag, key, INT_TYPE, val, sizeof(val));
+       if (ret == SYSTEM_INFO_ERROR_NONE)
+               goto out;
+
+       if (tag == TAG_TYPE_CUSTOM) {
+               ret = external_get_value(TAG_TYPE_CUSTOM_STR, key, INT_TYPE, &valp);
+               if (ret == SYSTEM_INFO_ERROR_NONE) {
+                       snprintf(val, sizeof(val), "%s", valp); //LCOV_EXCL_LINE
+                       free(valp); //LCOV_EXCL_LINE
+                       goto out; //LCOV_EXCL_LINE
+               }
        }
 
-       ret = system_info_get_value_from_config_xml(PLATFORM_TAG, key, BOOL_TYPE, &
-string);
-       if (ret) {
-               LOGE("cannot get %s", key);
-               return ret;
-       }
+       _E("Invalid key (%s), type:integer", key);
 
-       if (!strcmp(string, "true") || !strcmp(string, "TRUE"))
-               *supported = true;
-       else
-               *supported = false;
+       return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
 
-       free(string);
+out:
+       *value = atoi(val);
 
        return SYSTEM_INFO_ERROR_NONE;
 }
 
-int system_info_get_platform_int(const char *key, int *value)
+static int system_info_get_double(enum tag_type tag, const char *key, double *value)
 {
        int ret;
-       int *ret_val;
-       char *string = NULL;
+       char val[128];
+       char *valp;
 
-       ret_val = (int *)value;
+       if (!key || !value)
+               return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
 
-       if (access(CONFIG_FILE_PATH, R_OK)) {
-               LOGE("cannot find file %s!!!", CONFIG_FILE_PATH);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
-       }
+       ret = db_get_value(tag, key, DBL_TYPE, val, sizeof(val));
+       if (ret == SYSTEM_INFO_ERROR_NONE)
+               goto out;
 
-       ret = system_info_get_value_from_config_xml(PLATFORM_TAG, key, INT_TYPE, &
-string);
-       if (ret) {
-               LOGE("cannot get %s", key);
-               return ret;
+       if (tag == TAG_TYPE_CUSTOM) {
+               ret = external_get_value(TAG_TYPE_CUSTOM_STR, key, DBL_TYPE, &valp);
+               if (ret == SYSTEM_INFO_ERROR_NONE) {
+                       snprintf(val, sizeof(val), "%s", valp); //LCOV_EXCL_LINE
+                       free(valp); //LCOV_EXCL_LINE
+                       goto out; //LCOV_EXCL_LINE
+               }
        }
 
-       *ret_val = atoi(string);
+       _E("Invalid key (%s), type:double", key);
 
-       free(string);
+       return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
+
+out:
+       *value = atof(val);
 
        return SYSTEM_INFO_ERROR_NONE;
 }
 
-int system_info_get_platform_double(const char *key, double *value)
+static int system_info_get_string(enum tag_type tag, const char *key, char **value)
 {
        int ret;
-       double *ret_val;
-       char *string = NULL;
+       char val[STR_MAX];
+       char *string;
+       char *valp;
 
-       ret_val = (double *)value;
+       if (!key || !value)
+               return SYSTEM_INFO_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
 
-       if (access(CONFIG_FILE_PATH, R_OK)) {
-               LOGE("cannot find file %s!!!", CONFIG_FILE_PATH);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
-       }
+       ret = db_get_value(tag, key, STR_TYPE, val, sizeof(val));
+       if (ret == SYSTEM_INFO_ERROR_NONE)
+               goto out;
 
-       ret = system_info_get_value_from_config_xml(PLATFORM_TAG, key, DBL_TYPE, &
-string);
-       if (ret) {
-               LOGE("cannot get %s", key);
-               return ret;
+       if (tag == TAG_TYPE_PLATFORM) {
+               ret = system_info_get_file(key, val, sizeof(val));
+               if (ret == SYSTEM_INFO_ERROR_NONE)
+                       goto out;
        }
 
-       *ret_val = atof(string);
-
-       free(string);
-
-       return SYSTEM_INFO_ERROR_NONE;
-}
+       if (tag == TAG_TYPE_CUSTOM) {
+               ret = external_get_value(TAG_TYPE_CUSTOM_STR, key, DBL_TYPE, &valp);
+               if (ret == SYSTEM_INFO_ERROR_NONE) {
+                       snprintf(val, sizeof(val), "%s", valp); //LCOV_EXCL_LINE
+                       free(valp); //LCOV_EXCL_LINE
+                       goto out; //LCOV_EXCL_LINE
+               }
+       }
 
-int system_info_get_platform_string(const char *key, char **value)
-{
-       int ret;
-       char *string = NULL;
+       _E("Invalid key (%s) type:string", key);
 
-       if (access(CONFIG_FILE_PATH, R_OK)) {
-               LOGE("cannot find file %s!!!", CONFIG_FILE_PATH);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
-       }
+       return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
 
-       ret = system_info_get_value_from_config_xml(PLATFORM_TAG, key, STR_TYPE, &
-string);
-       if (ret) {
-               LOGE("cannot get %s", key);
-               return ret;
+out:
+       string = strdup(val);
+       if (!string) {
+               _E("malloc failed"); //LCOV_EXCL_LINE
+               return SYSTEM_INFO_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
        }
 
        *value = string;
@@ -748,111 +421,84 @@ string);
        return SYSTEM_INFO_ERROR_NONE;
 }
 
-int system_info_get_custom_bool(const char *key, bool *value)
+API int system_info_get_platform_bool(const char *key, bool *value)
 {
-       int ret;
-       bool *supported;
-       char *string = NULL;
-
-       supported = (bool *)value;
-
-       if (access(CONFIG_FILE_PATH, R_OK)) {
-               LOGE("cannot find file %s!!!", CONFIG_FILE_PATH);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
-       }
-
-       ret = system_info_get_value_from_config_xml(CUSTOM_TAG, key, BOOL_TYPE, &
-string);
-       if (ret) {
-               LOGI("cannot get %s", key);
-               *supported = false;
-               return SYSTEM_INFO_ERROR_NONE;
-       }
-
-       if (!strcmp(string, "true") || !strcmp(string, "TRUE"))
-               *supported = true;
-       else
-               *supported = false;
-
-       free(string);
-
-       return SYSTEM_INFO_ERROR_NONE;
+       return system_info_get_bool(TAG_TYPE_PLATFORM, key, value);
 }
 
-int system_info_get_custom_int(const char *key, int *value)
+API int system_info_get_platform_int(const char *key, int *value)
 {
-       int ret;
-       int *ret_val;
-       char *string = NULL;
-
-       ret_val = (int *)value;
-
-       if (access(CONFIG_FILE_PATH, R_OK)) {
-               LOGE("cannot find file %s!!!", CONFIG_FILE_PATH);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
-       }
-
-       ret = system_info_get_value_from_config_xml(CUSTOM_TAG, key, INT_TYPE, &
-string);
-       if (ret) {
-               LOGI("cannot get %s", key);
-               *ret_val = 0;
-               return SYSTEM_INFO_ERROR_NONE;
-       }
-
-       *ret_val = atoi(string);
-
-       free(string);
-
-       return SYSTEM_INFO_ERROR_NONE;
+       return system_info_get_int(TAG_TYPE_PLATFORM, key, value);
 }
 
-int system_info_get_custom_double(const char *key, double *value)
+API int system_info_get_platform_double(const char *key, double *value)
 {
-       int ret;
-       double *ret_val;
-       char *string = NULL;
+       return system_info_get_double(TAG_TYPE_PLATFORM, key, value);
+}
 
-       ret_val = (double *)value;
+API int system_info_get_platform_string(const char *key, char **value)
+{
+       return system_info_get_string(TAG_TYPE_PLATFORM, key, value);
+}
 
-       if (access(CONFIG_FILE_PATH, R_OK)) {
-               LOGE("cannot find file %s!!!", CONFIG_FILE_PATH);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
-       }
+API int system_info_get_custom_bool(const char *key, bool *value)
+{
+       return system_info_get_bool(TAG_TYPE_CUSTOM, key, value);
+}
 
-       ret = system_info_get_value_from_config_xml(CUSTOM_TAG, key, DBL_TYPE, &
-string);
-       if (ret) {
-               LOGI("cannot get %s", key);
-               *ret_val = 0;
-               return SYSTEM_INFO_ERROR_NONE;
-       }
+API int system_info_get_custom_int(const char *key, int *value)
+{
+       return system_info_get_int(TAG_TYPE_CUSTOM, key, value);
+}
 
-       *ret_val = atof(string);
+API int system_info_get_custom_double(const char *key, double *value)
+{
+       return system_info_get_double(TAG_TYPE_CUSTOM, key, value);
+}
 
-       free(string);
+API int system_info_get_custom_string(const char *key, char **value)
+{
+       return system_info_get_string(TAG_TYPE_CUSTOM, key, value);
+}
 
-       return SYSTEM_INFO_ERROR_NONE;
+API int system_info_get_platform_type(const char *key, system_info_type_e *type)
+{
+       return system_info_get_type(TAG_TYPE_PLATFORM, key, type);
 }
 
-int system_info_get_custom_string(const char *key, char **value)
+API int system_info_get_custom_type(const char *key, system_info_type_e *type)
 {
        int ret;
-       char *string = NULL;
+       char *val = NULL;
+       size_t len;
 
-       if (access(CONFIG_FILE_PATH, R_OK)) {
-               LOGE("cannot find file %s!!!", CONFIG_FILE_PATH);
-               return SYSTEM_INFO_ERROR_IO_ERROR;
-       }
+       ret = system_info_get_type(TAG_TYPE_CUSTOM, key, type);
+       if (ret == SYSTEM_INFO_ERROR_NONE)
+               return SYSTEM_INFO_ERROR_NONE;
 
-       ret = system_info_get_value_from_config_xml(CUSTOM_TAG, key, STR_TYPE, &
-string);
-       if (ret) {
-               LOGE("cannot get %s info from %s!!!", key, CONFIG_FILE_PATH);
-               return ret;
+       ret = external_get_type(TAG_TYPE_CUSTOM_STR, key, &val);
+       if (ret != SYSTEM_INFO_ERROR_NONE) {
+               _E("Failed to get type of key (%s)", key);
+               return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
        }
 
-       *value = string;
+       //LCOV_EXCL_START
+       len = strlen(val) + 1;
+       if (!strncmp(BOOL_TYPE, val, len))
+               *type = SYSTEM_INFO_BOOL;
+       else if (!strncmp(INT_TYPE, val, len))
+               *type = SYSTEM_INFO_INT;
+       else if (!strncmp(DBL_TYPE, val, len))
+               *type = SYSTEM_INFO_DOUBLE;
+       else if (!strncmp(STR_TYPE, val, len))
+               *type = SYSTEM_INFO_STRING;
+       else {
+               _E("Invalid type (%s)", val);
+               free(val);
+               return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
+       }
 
+       free(val);
        return SYSTEM_INFO_ERROR_NONE;
+       //LCOV_EXCL_STOP
 }