Fix bugs
[platform/core/uifw/stt.git] / server / sttd_server.c
index 5416556..47bea93 100644 (file)
@@ -1,5 +1,5 @@
 /*
-*  Copyright (c) 2011-2014 Samsung Electronics Co., Ltd All Rights Reserved 
+*  Copyright (c) 2011-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.
 *  You may obtain a copy of the License at
@@ -11,6 +11,7 @@
 *  limitations under the License.
 */
 
+#include <pthread.h>
 #include <sound_manager.h>
 #include <wav_player.h>
 
@@ -23,6 +24,9 @@
 #include "sttd_recorder.h"
 #include "sttd_server.h"
 
+static pthread_mutex_t sttpe_result_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t sttpe_result_time_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 
 /*
 * STT Server static variable
@@ -34,20 +38,14 @@ static double g_recording_timeout = 60;
 Ecore_Timer*   g_recording_timer = NULL;
 Ecore_Timer*   g_processing_timer = NULL;
 
-static Eina_Bool g_stt_daemon_exist = EINA_TRUE;
-
 static int g_recording_log_count = 0;
 
+static GList *g_proc_list = NULL;
+
 /*
 * STT Server Callback Functions
 */
-
-Eina_Bool sttd_get_daemon_exist()
-{
-       return g_stt_daemon_exist;
-}
-
-Eina_Bool __stop_by_silence(void *data)
+void __stop_by_silence(void *data)
 {
        SLOG(LOG_DEBUG, TAG_STTD, "===== Stop by silence detection");
 
@@ -57,11 +55,11 @@ Eina_Bool __stop_by_silence(void *data)
 
        int ret;
        if (0 != uid) {
-               ret = sttd_server_stop(uid); 
+               ret = sttd_server_stop(uid);
                if (0 > ret) {
-                       return EINA_FALSE;
+                       return;
                }
-       
+
                if (STTD_RESULT_STATE_DONE == ret) {
                        ret = sttdc_send_set_state(uid, (int)APP_STATE_PROCESSING);
                        if (0 != ret) {
@@ -79,7 +77,7 @@ Eina_Bool __stop_by_silence(void *data)
        SLOG(LOG_DEBUG, TAG_STTD, "=====");
        SLOG(LOG_DEBUG, TAG_STTD, "  ");
 
-       return EINA_FALSE;
+       return;
 }
 
 static void __cancel_recognition_internal()
@@ -112,7 +110,7 @@ static void __cancel_recognition_internal()
        }
 }
 
-Eina_Bool __cancel_by_error(void *data)
+static void __cancel_by_error(void *data)
 {
        SLOG(LOG_DEBUG, TAG_STTD, "===== Cancel by error");
 
@@ -121,7 +119,7 @@ Eina_Bool __cancel_by_error(void *data)
        SLOG(LOG_DEBUG, TAG_STTD, "=====");
        SLOG(LOG_DEBUG, TAG_STTD, "  ");
 
-       return EINA_FALSE;
+       return;
 }
 
 int __server_audio_recorder_callback(const void* data, const unsigned int length)
@@ -131,7 +129,7 @@ int __server_audio_recorder_callback(const void* data, const unsigned int length
 
        if (NULL == data || 0 == length) {
                SLOG(LOG_WARN, TAG_STTD, "[Server WARNING] Recording data is not valid");
-               ecore_timer_add(0, __cancel_by_error, NULL);
+               ecore_main_loop_thread_safe_call_async(__cancel_by_error, NULL);
                return -1;
        }
 
@@ -139,12 +137,12 @@ int __server_audio_recorder_callback(const void* data, const unsigned int length
        if (0 != uid) {
                ret = sttd_engine_agent_set_recording_data(uid, data, length);
                if (ret < 0) {
-                        ecore_timer_add(0, __cancel_by_error, NULL);
-                        return -1;
+                       ecore_main_loop_thread_safe_call_async(__cancel_by_error, NULL);
+                       return -1;
                }
                g_recording_log_count++;
                if (200 <= g_recording_log_count) {
-                       SECURE_SLOG(LOG_DEBUG, TAG_STTD, "=== Set recording data ===");
+                       SLOG(LOG_DEBUG, TAG_STTD, "=== Set recording data ===");
                        g_recording_log_count = 0;
                }
        } else {
@@ -169,7 +167,7 @@ void __server_audio_interrupt_callback()
        SLOG(LOG_DEBUG, TAG_STTD, "  ");
 }
 
-Eina_Bool __cancel_by_no_record(void *data)
+void __cancel_by_no_record(void *data)
 {
        SLOG(LOG_DEBUG, TAG_STTD, "===== Cancel by no record");
 
@@ -177,14 +175,17 @@ Eina_Bool __cancel_by_no_record(void *data)
 
        SLOG(LOG_DEBUG, TAG_STTD, "=====");
        SLOG(LOG_DEBUG, TAG_STTD, "  ");
-       
-       return EINA_FALSE;
+
+       return;
 }
 
 void __server_recognition_result_callback(sttp_result_event_e event, const char* type,
                                        const char** data, int data_count, const char* msg, void *user_data)
 {
-       SLOG(LOG_DEBUG, TAG_STTD, "===== Recognition Result Callback");
+       // critical section
+       pthread_mutex_lock(&sttpe_result_mutex);
+
+       SLOG(LOG_DEBUG, TAG_STTD, "===== RESULT event[%d] type[%s] data[%p] data_count[%d]", event, type, data, data_count);
 
        /* check uid */
        int uid = stt_client_get_current_recognition();
@@ -194,17 +195,18 @@ void __server_recognition_result_callback(sttp_result_event_e event, const char*
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] uid is NOT valid ");
                SLOG(LOG_DEBUG, TAG_STTD, "=====");
                SLOG(LOG_DEBUG, TAG_STTD, "  ");
+               pthread_mutex_unlock(&sttpe_result_mutex);
                return;
        }
 
-       SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] uid (%d), event(%d)", uid, event);
+       SLOG(LOG_DEBUG, TAG_STTD, "[Server] uid (%d), event(%d)", uid, event);
 
        /* send result to client */
        if (STTP_RESULT_EVENT_FINAL_RESULT == event) {
-               if (APP_STATE_PROCESSING != state ) {
+               if (APP_STATE_PROCESSING != state) {
                        SLOG(LOG_WARN, TAG_STTD, "[Server WARNING] Current state is NOT 'Processing'.");
                }
-               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] the size of result from engine is '%d'", data_count);
+               SLOG(LOG_DEBUG, TAG_STTD, "[Server] the size of result from engine is '%d'", data_count);
 
                /* Delete timer for processing time out */
                if (NULL != g_processing_timer) {
@@ -217,7 +219,7 @@ void __server_recognition_result_callback(sttp_result_event_e event, const char*
 
                if (NULL == data || 0 == data_count) {
                        if (0 != sttdc_send_result(uid, event, NULL, 0, msg)) {
-                               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send result");        
+                               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send result");
                                int reason = (int)STTD_ERROR_OPERATION_FAILED;
 
                                if (0 != sttdc_send_error_signal(uid, reason, "Fail to send recognition result")) {
@@ -226,7 +228,7 @@ void __server_recognition_result_callback(sttp_result_event_e event, const char*
                        }
                } else {
                        if (0 != sttdc_send_result(uid, event, data, data_count, msg)) {
-                               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send result");        
+                               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send result");
                                int reason = (int)STTD_ERROR_OPERATION_FAILED;
 
                                if (0 != sttdc_send_error_signal(uid, reason, "Fail to send recognition result")) {
@@ -240,7 +242,7 @@ void __server_recognition_result_callback(sttp_result_event_e event, const char*
                stt_client_unset_current_recognition();
 
        } else if (STTP_RESULT_EVENT_PARTIAL_RESULT == event) {
-               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] The partial result from engine is event[%d] data_count[%d]", event,  data_count);
+               SLOG(LOG_DEBUG, TAG_STTD, "[Server] The partial result from engine is event[%d] data_count[%d]", event,  data_count);
 
                sttd_config_time_save();
                sttd_config_time_reset();
@@ -268,7 +270,7 @@ void __server_recognition_result_callback(sttp_result_event_e event, const char*
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send result ");
 
                        /* send error msg */
-                       int reason = (int)STTD_ERROR_INVALID_STATE;     
+                       int reason = (int)STTD_ERROR_INVALID_STATE;
                        if (0 != sttdc_send_error_signal(uid, reason, "[ERROR] Fail to send recognition result")) {
                                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send error info ");
                        }
@@ -283,13 +285,16 @@ void __server_recognition_result_callback(sttp_result_event_e event, const char*
 
        SLOG(LOG_DEBUG, TAG_STTD, "=====");
        SLOG(LOG_DEBUG, TAG_STTD, "  ");
+       pthread_mutex_unlock(&sttpe_result_mutex);
 
        return;
 }
 
 bool __server_result_time_callback(int index, sttp_result_time_event_e event, const char* text, long start_time, long end_time, void* user_data)
 {
-       SLOG(LOG_DEBUG, TAG_STTD, "[Server] index(%d) event(%d) text(%s) start(%ld) end(%ld)", 
+       pthread_mutex_lock(&sttpe_result_time_mutex);
+
+       SLOG(LOG_DEBUG, TAG_STTD, "[Server] index(%d) event(%d) text(%s) start(%ld) end(%ld)",
                index, event, text, start_time, end_time);
 
        if (0 == index) {
@@ -297,12 +302,16 @@ bool __server_result_time_callback(int index, sttp_result_time_event_e event, co
                ret = sttd_config_time_add(index, (int)event, text, start_time, end_time);
                if (0 != ret) {
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to add time info");
+                       pthread_mutex_unlock(&sttpe_result_time_mutex);
                        return false;
                }
        } else {
+               pthread_mutex_unlock(&sttpe_result_time_mutex);
                return false;
        }
 
+       pthread_mutex_unlock(&sttpe_result_time_mutex);
+
        return true;
 }
 
@@ -324,11 +333,14 @@ void __server_silence_dectection_callback(sttp_silence_type_e type, void *user_p
                }
 
                if (STTP_SILENCE_TYPE_NO_RECORD_TIMEOUT == type) {
-                       SECURE_SLOG(LOG_DEBUG, TAG_STTD, "Silence Detection type - No Record");
-                       ecore_timer_add(0, __cancel_by_no_record, NULL);
+                       SLOG(LOG_DEBUG, TAG_STTD, "Silence Detection type - No Record");
+                       ecore_main_loop_thread_safe_call_async(__cancel_by_no_record, NULL);
+                       if (0 != sttdc_send_error_signal(uid, STTP_ERROR_NO_SPEECH, "No speech while recording")) {
+                               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] No speech while recording");
+                       }
                } else if (STTP_SILENCE_TYPE_END_OF_SPEECH_DETECTED == type) {
-                       SECURE_SLOG(LOG_DEBUG, TAG_STTD, "Silence Detection type - End of Speech");
-                       ecore_timer_add(0, __stop_by_silence, NULL);
+                       SLOG(LOG_DEBUG, TAG_STTD, "Silence Detection type - End of Speech");
+                       ecore_main_loop_thread_safe_call_async(__stop_by_silence, NULL);
                }
        } else {
                SLOG(LOG_WARN, TAG_STTD, "[Server WARNING] Current recogntion uid is not valid ");
@@ -340,13 +352,13 @@ void __server_silence_dectection_callback(sttp_silence_type_e type, void *user_p
        return;
 }
 
-void __sttd_server_engine_changed_cb(const char* engine_id, const char* language, bool support_silence, void* user_data)
+void __sttd_server_engine_changed_cb(const char* engine_id, const char* language, bool support_silence, bool need_credential, void* user_data)
 {
        if (NULL == engine_id) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Engine id is NULL");
                return;
        } else {
-               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] New default engine : %s", engine_id);
+               SLOG(LOG_DEBUG, TAG_STTD, "[Server] New default engine : %s", engine_id);
        }
 
        /* need to change state of app to ready */
@@ -354,7 +366,7 @@ void __sttd_server_engine_changed_cb(const char* engine_id, const char* language
        uid = stt_client_get_current_recognition();
 
        if (0 != uid) {
-               SECURE_SLOG(LOG_ERROR, TAG_STTD, "[Server] Set ready state of uid(%d)", uid);
+               SLOG(LOG_ERROR, TAG_STTD, "[Server] Set ready state of uid(%d)", uid);
 
                sttd_server_cancel(uid);
                sttdc_send_set_state(uid, (int)APP_STATE_READY);
@@ -372,7 +384,7 @@ void __sttd_server_engine_changed_cb(const char* engine_id, const char* language
                if (0 != ret)
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set default lang : result(%d)", ret);
        }
-       
+
        ret = sttd_engine_agent_set_silence_detection(support_silence);
        if (0 != ret)
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to Result(%d)", ret);
@@ -386,7 +398,7 @@ void __sttd_server_language_changed_cb(const char* language, void* user_data)
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] language is NULL");
                return;
        } else {
-               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] Get language changed : %s", language);
+               SLOG(LOG_DEBUG, TAG_STTD, "[Server] Get language changed : %s", language);
        }
 
        int ret = sttd_engine_agent_set_default_language(language);
@@ -398,7 +410,7 @@ void __sttd_server_language_changed_cb(const char* language, void* user_data)
 
 void __sttd_server_silence_changed_cb(bool value, void* user_data)
 {
-       SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] Get silence detection changed : %s", value ? "on" : "off");
+       SLOG(LOG_DEBUG, TAG_STTD, "[Server] Get silence detection changed : %s", value ? "on" : "off");
 
        int ret = 0;
        ret = sttd_engine_agent_set_silence_detection(value);
@@ -416,7 +428,15 @@ int sttd_initialize()
 {
        int ret = 0;
 
-       if (sttd_config_initialize(__sttd_server_engine_changed_cb, __sttd_server_language_changed_cb, 
+       if (0 != pthread_mutex_init(&sttpe_result_mutex, NULL)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to initialize sttpe result mutex.");
+       }
+
+       if (0 != pthread_mutex_init(&sttpe_result_time_mutex, NULL)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to initialize sttpe sttpe_result_time_mutex.");
+       }
+
+       if (sttd_config_initialize(__sttd_server_engine_changed_cb, __sttd_server_language_changed_cb,
                __sttd_server_silence_changed_cb, NULL)) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to initialize config.");
        }
@@ -424,6 +444,7 @@ int sttd_initialize()
        ret = sttd_recorder_initialize(__server_audio_recorder_callback, __server_audio_interrupt_callback);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to initialize recorder : result(%d)", ret);
+               return ret;
        }
 
        /* Engine Agent initialize */
@@ -433,7 +454,7 @@ int sttd_initialize()
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to engine agent initialize : result(%d)", ret);
                return ret;
        }
-       
+
        /* Update engine list */
        ret = sttd_engine_agent_initialize_engine_list();
        if (0 != ret) {
@@ -452,6 +473,23 @@ int sttd_initialize()
 
 int sttd_finalize()
 {
+       if (0 != pthread_mutex_destroy(&sttpe_result_mutex)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to destroy sttpe result mutex.");
+       }
+
+       if (0 != pthread_mutex_destroy(&sttpe_result_time_mutex)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to destroy sttpe_result_time_mutex.");
+       }
+
+       GList *iter = NULL;
+       if (0 < g_list_length(g_proc_list)) {
+               iter = g_list_first(g_proc_list);
+               while (NULL != iter) {
+                       g_proc_list = g_list_remove_link(g_proc_list, iter);
+                       iter = g_list_first(g_proc_list);
+               }
+       }
+
        sttd_recorder_deinitialize();
 
        sttd_config_finalize();
@@ -461,12 +499,52 @@ int sttd_finalize()
        return STTD_ERROR_NONE;
 }
 
+static void __read_proc()
+{
+       DIR *dp = NULL;
+       struct dirent entry;
+       struct dirent *dirp = NULL;
+       int ret = -1;
+       int tmp;
+
+       GList *iter = NULL;
+       if (0 < g_list_length(g_proc_list)) {
+               iter = g_list_first(g_proc_list);
+               while (NULL != iter) {
+                       g_proc_list = g_list_remove_link(g_proc_list, iter);
+                       iter = g_list_first(g_proc_list);
+               }
+       }
+
+       dp = opendir("/proc");
+       if (NULL == dp) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Fail to open proc");
+       } else {
+               do {
+                       ret = readdir_r(dp, &entry, &dirp);
+                       if (0 != ret) {
+                               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Fail to readdir");
+                               break;
+                       }
+
+                       if (NULL != dirp) {
+                               tmp = atoi(dirp->d_name);
+                               if (0 >= tmp)   continue;
+                               g_proc_list = g_list_append(g_proc_list, GINT_TO_POINTER(tmp));
+                       }
+               } while (NULL != dirp);
+               closedir(dp);
+       }
+       return;
+}
+
 Eina_Bool sttd_cleanup_client(void *data)
 {
        int* client_list = NULL;
        int client_count = 0;
-       int result;
        int i = 0;
+       int j = 0;
+       bool exist = false;
 
        if (0 != sttd_client_get_list(&client_list, &client_count)) {
                if (NULL != client_list)
@@ -477,16 +555,43 @@ Eina_Bool sttd_cleanup_client(void *data)
 
        if (NULL != client_list) {
                SLOG(LOG_DEBUG, TAG_STTD, "===== Clean up client ");
+               
+               __read_proc();
+
+               for (i = 0; i < client_count; i++) {
+                       int pid = sttd_client_get_pid(client_list[i]);
+                       if (0 > pid) {
+                               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Invalid pid");
+                               continue;
+                       }
+
+                       exist = false;
+                       GList *iter = NULL;
+                       for (j = 0; j < g_list_length(g_proc_list); j++) {
+                               iter = g_list_nth(g_proc_list, j);
+                               if (NULL != iter) {
+                                       if (pid == GPOINTER_TO_INT(iter->data)) {
+                                               SLOG(LOG_DEBUG, TAG_STTD, "uid (%d) is running", client_list[i]);
+                                               exist = true;
+                                               break;
+                                       }
+                               }
+                       }
 
-               for (i = 0;i < client_count;i++) {
+                       if (false == exist) {
+                               SLOG(LOG_ERROR, TAG_STTD, "uid (%d) should be removed", client_list[i]);
+                               sttd_server_finalize(client_list[i]);
+                       }
+#if 0
                        result = sttdc_send_hello(client_list[i]);
 
                        if (0 == result) {
-                               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] uid(%d) should be removed.", client_list[i]);
+                               SLOG(LOG_DEBUG, TAG_STTD, "[Server] uid(%d) should be removed.", client_list[i]);
                                sttd_server_finalize(client_list[i]);
                        } else if (-1 == result) {
                                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Hello result has error");
                        }
+#endif
                }
 
                SLOG(LOG_DEBUG, TAG_STTD, "=====");
@@ -502,18 +607,20 @@ Eina_Bool sttd_cleanup_client(void *data)
 * STT Server Functions for Client
 */
 
-int sttd_server_initialize(int pid, int uid, bool* silence)
+int sttd_server_initialize(int pid, int uid, bool* silence, bool* credential)
 {
        if (false == sttd_engine_agent_is_default_engine()) {
                /* Update installed engine */
                sttd_engine_agent_initialize_engine_list();
-               
+
                if (false == sttd_engine_agent_is_default_engine()) {
                        SLOG(LOG_WARN, TAG_STTD, "[Server WARNING] No stt-engine");
                        return STTD_ERROR_ENGINE_NOT_FOUND;
                }
        }
 
+       int ret = STTD_ERROR_NONE;
+
        /* check if uid is valid */
        app_state_e state;
        if (0 == sttd_client_get_state(uid, &state)) {
@@ -522,20 +629,29 @@ int sttd_server_initialize(int pid, int uid, bool* silence)
        }
 
        /* load engine */
-       if (0 != sttd_engine_agent_load_current_engine(uid, NULL)) {
+       ret = sttd_engine_agent_load_current_engine(uid, NULL);
+       if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to load default engine");
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
-       if (0 != sttd_engine_agent_get_option_supported(uid, silence)) {
+       ret = sttd_engine_agent_get_option_supported(uid, silence);
+       if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get engine options supported");
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
+       }
+
+       ret = sttd_engine_agent_is_credential_needed(uid, credential);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get credential necessity");
+               return ret;
        }
 
        /* Add client information to client manager */
-       if (0 != sttd_client_add(pid, uid)) {
+       ret = sttd_client_add(pid, uid);
+       if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to add client info");
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        return STTD_ERROR_NONE;
@@ -578,7 +694,7 @@ int sttd_server_finalize(int uid)
 
                stt_client_unset_current_recognition();
        }
-       
+
        if (0 != sttd_engine_agent_unload_current_engine(uid)) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to unload engine");
        }
@@ -590,10 +706,10 @@ int sttd_server_finalize(int uid)
 
        /* unload engine, if ref count of client is 0 */
        if (0 == sttd_client_get_ref_count()) {
-               g_stt_daemon_exist = EINA_FALSE;
+//             sttd_dbus_close_connection();
                ecore_timer_add(0, __quit_ecore_loop, NULL);
        }
-       
+
        return STTD_ERROR_NONE;
 }
 
@@ -608,7 +724,7 @@ int sttd_server_get_supported_engines(int uid, GSList** engine_list)
 
        /* Check state of uid */
        if (APP_STATE_READY != state) {
-               SECURE_SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] The state of uid(%d) is not Ready", uid);
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] The state of uid(%d) is not Ready", uid);
                return STTD_ERROR_INVALID_STATE;
        }
 
@@ -616,13 +732,13 @@ int sttd_server_get_supported_engines(int uid, GSList** engine_list)
        ret = sttd_engine_agent_get_engine_list(engine_list);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get engine list");
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        return STTD_ERROR_NONE;
 }
 
-int sttd_server_set_current_engine(int uid, const char* engine_id, bool* silence)
+int sttd_server_set_current_engine(int uid, const char* engine_id, bool* silence, bool* credential)
 {
        /* Check if uid is valid */
        app_state_e state;
@@ -633,7 +749,7 @@ int sttd_server_set_current_engine(int uid, const char* engine_id, bool* silence
 
        /* Check state of uid */
        if (APP_STATE_READY != state) {
-               SECURE_SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] The state of uid(%d) is not Ready", uid);
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] The state of uid(%d) is not Ready", uid);
                return STTD_ERROR_INVALID_STATE;
        }
 
@@ -641,13 +757,18 @@ int sttd_server_set_current_engine(int uid, const char* engine_id, bool* silence
        ret = sttd_engine_agent_load_current_engine(uid, engine_id);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set engine : %d", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        ret = sttd_engine_agent_get_option_supported(uid, silence);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to engine options : %d", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
+       }
+
+       if (0 != sttd_engine_agent_is_credential_needed(uid, credential)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get credential necessity");
+               return ret;
        }
 
        return STTD_ERROR_NONE;
@@ -664,32 +785,32 @@ int sttd_server_get_current_engine(int uid, char** engine_id)
 
        /* Check state of uid */
        if (APP_STATE_READY != state) {
-               SECURE_SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] The state of uid(%d) is not Ready", uid);
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] The state of uid(%d) is not Ready", uid);
                return STTD_ERROR_INVALID_STATE;
        }
-       
+
        int ret;
        ret = sttd_engine_agent_get_current_engine(uid, engine_id);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get engine : %d", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        return STTD_ERROR_NONE;
 }
 
-int sttd_server_check_agg_agreed(int uid, const char* appid, bool* available)
+int sttd_server_check_app_agreed(int uid, const char* appid, bool* available)
 {
        /* Check if uid is valid */
        app_state_e state;
        if (0 != sttd_client_get_state(uid, &state)) {
-               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] uid is NOT valid "); 
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] uid is NOT valid ");
                return STTD_ERROR_INVALID_PARAMETER;
        }
 
        /* Check state of uid */
        if (APP_STATE_READY != state) {
-               SECURE_SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] The state of uid(%d) is not Ready", uid);
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] The state of uid(%d) is not Ready", uid);
                return STTD_ERROR_INVALID_STATE;
        }
 
@@ -699,7 +820,7 @@ int sttd_server_check_agg_agreed(int uid, const char* appid, bool* available)
        ret = sttd_engine_agent_check_app_agreed(uid, appid, &temp);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get engine available : %d", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        if (true == temp) {
@@ -726,7 +847,7 @@ int sttd_server_get_supported_languages(int uid, GSList** lang_list)
        int ret = sttd_engine_agent_supported_langs(uid, lang_list);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get supported languages");
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        SLOG(LOG_DEBUG, TAG_STTD, "[Server SUCCESS] sttd_server_get_supported_languages");
@@ -750,9 +871,9 @@ int sttd_server_get_current_langauage(int uid, char** current_lang)
 
        /*get current language from engine */
        int ret = sttd_engine_agent_get_default_lang(uid, current_lang);
-       if (0 != ret) { 
+       if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get default language :result(%d)", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        SLOG(LOG_DEBUG, TAG_STTD, "[Server SUCCESS] Get default language");
@@ -760,6 +881,60 @@ int sttd_server_get_current_langauage(int uid, char** current_lang)
        return STTD_ERROR_NONE;
 }
 
+int sttd_server_set_private_data(int uid, const char* key, const char* data)
+{
+       /* check if uid is valid */
+       app_state_e state;
+       if (0 != sttd_client_get_state(uid, &state)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] uid is NOT valid ");
+               return STTD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (NULL == key || NULL == data) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Input parameter is NULL");
+               return STTD_ERROR_INVALID_PARAMETER;
+       }
+
+       /* set private data to engine */
+       int ret = -1;
+       ret = sttd_engine_agent_set_private_data(uid, key, data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set private data :result(%d)", ret);
+               return ret;
+       }
+
+       SLOG(LOG_DEBUG, TAG_STTD, "[Server SUCCESS] Set private data");
+
+       return STTD_ERROR_NONE;
+}
+
+int sttd_server_get_private_data(int uid, const char* key, char** data)
+{
+       /* check if uid is valid */
+       app_state_e state;
+       if (0 != sttd_client_get_state(uid, &state)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] uid is NOT valid ");
+               return STTD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (NULL == key || NULL == data) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Input parameter is NULL");
+               return STTD_ERROR_INVALID_PARAMETER;
+       }
+
+       /* get private data to engine */
+       int ret = -1;
+       ret = sttd_engine_agent_get_private_data(uid, key, data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get private data :result(%d)", ret);
+               return ret;
+       }
+
+       SLOG(LOG_DEBUG, TAG_STTD, "[Server SUCCESS] Get private data");
+
+       return STTD_ERROR_NONE;
+}
+
 int sttd_server_is_recognition_type_supported(int uid, const char* type, int* support)
 {
        /* check if uid is valid */
@@ -776,14 +951,14 @@ int sttd_server_is_recognition_type_supported(int uid, const char* type, int* su
 
        bool temp;
        int ret = sttd_engine_agent_is_recognition_type_supported(uid, type, &temp);
-       if (0 != ret) { 
+       if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get recognition type supported : result(%d)", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
-       
+
        *support = (int)temp;
 
-       SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server SUCCESS] recognition type supporting is %s", *support ? "true" : "false");
+       SLOG(LOG_DEBUG, TAG_STTD, "[Server SUCCESS] recognition type supporting is %s", *support ? "true" : "false");
 
        return STTD_ERROR_NONE;
 }
@@ -798,9 +973,9 @@ int sttd_server_set_start_sound(int uid, const char* file)
        }
 
        int ret = sttd_client_set_start_sound(uid, file);
-       if (0 != ret) { 
+       if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set start sound file : result(%d)", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        return 0;
@@ -816,16 +991,17 @@ int sttd_server_set_stop_sound(int uid, const char* file)
        }
 
        int ret = sttd_client_set_stop_sound(uid, file);
-       if (0 != ret) { 
+       if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set start sound file : result(%d)", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        return 0;
 }
 
+#if 0
 Eina_Bool __check_recording_state(void *data)
-{      
+{
        /* current uid */
        int uid = stt_client_get_current_recognition();
        if (0 == uid)
@@ -834,18 +1010,18 @@ Eina_Bool __check_recording_state(void *data)
        app_state_e state;
        if (0 != sttdc_send_get_state(uid, (int*)&state)) {
                /* client is removed */
-               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] uid(%d) should be removed.", uid);
+               SLOG(LOG_DEBUG, TAG_STTD, "[Server] uid(%d) should be removed.", uid);
                sttd_server_finalize(uid);
                return EINA_FALSE;
        }
 
        if (APP_STATE_READY == state) {
                /* Cancel stt */
-               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] The state of uid(%d) is 'Ready'. The daemon should cancel recording", uid);
+               SLOG(LOG_DEBUG, TAG_STTD, "[Server] The state of uid(%d) is 'Ready'. The daemon should cancel recording", uid);
                sttd_server_cancel(uid);
        } else if (APP_STATE_PROCESSING == state) {
                /* Cancel stt and send change state */
-               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] The state of uid(%d) is 'Processing'. The daemon should cancel recording", uid);
+               SLOG(LOG_DEBUG, TAG_STTD, "[Server] The state of uid(%d) is 'Processing'. The daemon should cancel recording", uid);
                sttd_server_cancel(uid);
                sttdc_send_set_state(uid, (int)APP_STATE_READY);
        } else {
@@ -856,6 +1032,7 @@ Eina_Bool __check_recording_state(void *data)
 
        return EINA_FALSE;
 }
+#endif
 
 Eina_Bool __stop_by_recording_timeout(void *data)
 {
@@ -879,8 +1056,10 @@ Eina_Bool __stop_by_recording_timeout(void *data)
        return EINA_FALSE;
 }
 
-void __sttd_server_recorder_start(int uid)
+void __sttd_server_recorder_start(void* data)
 {
+       intptr_t puid = (intptr_t)data;
+       int uid = (int)puid;
        int current_uid = stt_client_get_current_recognition();
 
        if (uid != current_uid) {
@@ -904,16 +1083,15 @@ void __sttd_start_sound_completed_cb(int id, void *user_data)
 {
        SLOG(LOG_DEBUG, TAG_STTD, "===== Start sound completed");
 
-       int uid = (int)user_data;
-       /* 4. after wav play callback, recorder start */
-       __sttd_server_recorder_start(uid);
+       /* After wav play callback, recorder start */
+       ecore_main_loop_thread_safe_call_async(__sttd_server_recorder_start, user_data);
 
        SLOG(LOG_DEBUG, TAG_STTD, "=====");
        SLOG(LOG_DEBUG, TAG_STTD, "  ");
        return;
 }
 
-int sttd_server_start(int uid, const char* lang, const char* recognition_type, int silence, const char* appid)
+int sttd_server_start(int uid, const char* lang, const char* recognition_type, int silence, const char* appid, const char* credential)
 {
        if (NULL == lang || NULL == recognition_type) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Input parameter is NULL");
@@ -939,7 +1117,7 @@ int sttd_server_start(int uid, const char* lang, const char* recognition_type, i
                ret = sttd_engine_agent_check_app_agreed(uid, appid, &temp);
                if (0 != ret) {
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get engine available : %d", ret);
-                       return STTD_ERROR_OPERATION_FAILED;
+                       return ret;
                }
 
                if (false == temp) {
@@ -959,9 +1137,10 @@ int sttd_server_start(int uid, const char* lang, const char* recognition_type, i
        }
 
        char* sound = NULL;
-       if (0 != sttd_client_get_start_sound(uid, &sound)) {
+       ret = sttd_client_get_start_sound(uid, &sound);
+       if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get start beep sound");
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        if (0 != stt_client_set_current_recognition(uid)) {
@@ -971,10 +1150,10 @@ int sttd_server_start(int uid, const char* lang, const char* recognition_type, i
        }
 
        /* engine start recognition */
-       SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] start : uid(%d), lang(%s), recog_type(%s)", 
+       SLOG(LOG_DEBUG, TAG_STTD, "[Server] start : uid(%d), lang(%s), recog_type(%s)",
                        uid, lang, recognition_type);
        if (NULL != sound)
-               SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Server] start sound : %s", sound);
+               SLOG(LOG_DEBUG, TAG_STTD, "[Server] start sound : %s", sound);
 
        /* 1. Set audio session */
        ret = sttd_recorder_set_audio_session();
@@ -990,7 +1169,8 @@ int sttd_server_start(int uid, const char* lang, const char* recognition_type, i
        /* 2. Request wav play */
        if (NULL != sound) {
                int id = 0;
-               ret = wav_player_start(sound, SOUND_TYPE_MEDIA, __sttd_start_sound_completed_cb, (void*)uid, &id);
+               intptr_t puid = (intptr_t)uid;
+               ret = wav_player_start(sound, SOUND_TYPE_MEDIA, __sttd_start_sound_completed_cb, (void*)puid, &id);
                if (WAV_PLAYER_ERROR_NONE != ret) {
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to play wav");
                        is_sound_done = true;
@@ -1002,7 +1182,7 @@ int sttd_server_start(int uid, const char* lang, const char* recognition_type, i
        }
 
        /* 3. Create recorder & engine initialize */
-       ret = sttd_engine_agent_recognize_start_engine(uid, lang, recognition_type, silence, NULL);
+       ret = sttd_engine_agent_recognize_start_engine(uid, lang, recognition_type, silence, credential, NULL);
        if (0 != ret) {
                stt_client_unset_current_recognition();
                sttd_recorder_unset_audio_session();
@@ -1032,9 +1212,12 @@ int sttd_server_start(int uid, const char* lang, const char* recognition_type, i
                        sttd_client_set_state(uid, APP_STATE_READY);
 
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to start recorder : result(%d)", ret);
-                       return STTD_ERROR_OPERATION_FAILED;
+                       return ret;
                }
 
+               /* Notify uid state change */
+               sttdc_send_set_state(uid, APP_STATE_RECORDING);
+
                SLOG(LOG_DEBUG, TAG_STTD, "[Server SUCCESS] Start recognition");
                return STTD_RESULT_STATE_DONE;
        }
@@ -1062,7 +1245,7 @@ Eina_Bool __time_out_for_processing(void *data)
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send result ");
 
                /* send error msg */
-               int reason = (int)STTD_ERROR_TIMED_OUT; 
+               int reason = (int)STTD_ERROR_TIMED_OUT;
                if (0 != sttdc_send_error_signal(uid, reason, "[ERROR] Fail to send recognition result")) {
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send error info ");
                }
@@ -1076,8 +1259,10 @@ Eina_Bool __time_out_for_processing(void *data)
        return EINA_FALSE;
 }
 
-void __sttd_server_engine_stop(int uid)
+void __sttd_server_engine_stop(void* data)
 {
+       intptr_t puid = (intptr_t)data;
+       int uid = (int)puid;
        /* change uid state */
        sttd_client_set_state(uid, APP_STATE_PROCESSING);
 
@@ -1105,9 +1290,8 @@ void __sttd_stop_sound_completed_cb(int id, void *user_data)
 {
        SLOG(LOG_DEBUG, TAG_STTD, "===== Stop sound completed");
 
-       int uid = (int)user_data;
        /* After wav play callback, engine stop */
-       __sttd_server_engine_stop(uid);
+       ecore_main_loop_thread_safe_call_async(__sttd_server_engine_stop, user_data);
 
        SLOG(LOG_DEBUG, TAG_STTD, "=====");
        SLOG(LOG_DEBUG, TAG_STTD, "  ");
@@ -1136,7 +1320,7 @@ int sttd_server_stop(int uid)
 
        char* sound = NULL;
        if (0 != sttd_client_get_stop_sound(uid, &sound)) {
-               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get start beep sound"); 
+               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to get start beep sound");
                return STTD_ERROR_OPERATION_FAILED;
        }
 
@@ -1148,16 +1332,17 @@ int sttd_server_stop(int uid)
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to stop recorder : result(%d)", ret);
                if (0 != sttd_engine_agent_recognize_cancel(uid)) {
-                               SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to cancel recognize");
+                       SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to cancel recognize");
                }
                if (NULL != sound)      free(sound);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
        /* 2. Request wav play */
        if (NULL != sound) {
                int id = 0;
-               ret = wav_player_start(sound, SOUND_TYPE_MEDIA, __sttd_stop_sound_completed_cb, (void*)uid, &id);
+               intptr_t puid = (intptr_t)uid;
+               ret = wav_player_start(sound, SOUND_TYPE_MEDIA, __sttd_stop_sound_completed_cb, (void*)puid, &id);
                if (WAV_PLAYER_ERROR_NONE != ret) {
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to play wav");
                } else {
@@ -1176,7 +1361,7 @@ int sttd_server_stop(int uid)
                ret = sttd_recorder_unset_audio_session();
                if (0 != ret) {
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to unset session : %d", ret);
-                       return STTD_ERROR_OPERATION_FAILED;
+                       return ret;
                }
 
                /* Stop engine */
@@ -1184,14 +1369,17 @@ int sttd_server_stop(int uid)
                if (0 != ret) {
                        stt_client_unset_current_recognition();
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to stop engine : result(%d)", ret);
-                       return STTD_ERROR_OPERATION_FAILED;
+                       return ret;
                }
 
                /* change uid state */
                sttd_client_set_state(uid, APP_STATE_PROCESSING);
 
+               /* Notify uid state change */
+               sttdc_send_set_state(uid, APP_STATE_PROCESSING);
+
                SLOG(LOG_DEBUG, TAG_STTD, "[Server SUCCESS] Stop recognition");
-               
+
                g_processing_timer = ecore_timer_add(g_processing_timeout, __time_out_for_processing, NULL);
 
                return STTD_RESULT_STATE_DONE;
@@ -1209,7 +1397,7 @@ int sttd_server_cancel(int uid)
                return STTD_ERROR_INVALID_PARAMETER;
        }
 
-       /* check uid state */ 
+       /* check uid state */
        if (APP_STATE_READY == state) {
                SLOG(LOG_WARN, TAG_STTD, "[Server WARNING] Current state is ready");
                return STTD_ERROR_NONE;
@@ -1232,8 +1420,8 @@ int sttd_server_cancel(int uid)
                int ret = sttd_recorder_unset_audio_session();
                if (0 != ret) {
                        SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to unset session : %d", ret);
-                       return STTD_ERROR_OPERATION_FAILED;
-               }               
+                       return ret;
+               }
        }
 
        /* change uid state */
@@ -1243,8 +1431,11 @@ int sttd_server_cancel(int uid)
        int ret = sttd_engine_agent_recognize_cancel(uid);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to cancel : result(%d)", ret);
-               return STTD_ERROR_OPERATION_FAILED;
+               return ret;
        }
 
+       /* Notify uid state change */
+       sttdc_send_set_state(uid, APP_STATE_READY);
+
        return STTD_ERROR_NONE;
 }