Add checker for feature and privilege to engine API 99/288899/3
authorSuyeon Hwang <stom.hwang@samsung.com>
Fri, 24 Feb 2023 07:35:02 +0000 (16:35 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Thu, 2 Mar 2023 08:30:45 +0000 (17:30 +0900)
- Issue:
The engine API did not check feature and privilege of the application
even if it was described on header file.

- Solution:
This patch adds new logic for checking the feature and privilege for
using STT. Through this patch, engine API can return error values about
feature and privilege.

Change-Id: I4423ecac6a2ef20c92c535252bdd401e899b34f9
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
include/stte.h
server/sttd_main.h
server/stte.c

index c8c9238..bf63ba6 100755 (executable)
@@ -214,7 +214,7 @@ typedef bool (*stte_supported_language_cb)(const char* language, void* user_data
 * @details This callback function is called by the engine service user to request for STT engine to be started.
 * @since_tizen 3.0
 * @remarks This callback function is mandatory and must be registered using stte_main().
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -232,7 +232,7 @@ typedef int (*stte_initialize_cb)(void);
 * @remarks This callback function is mandatory and must be registered using stte_main().
 *          NOTE that the engine may be terminated automatically.
 *          When this callback function is invoked, the release of resources is necessary.
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_STATE Not initialized
@@ -249,7 +249,7 @@ typedef int (*stte_deinitialize_cb)(void);
 *          If 'stte_supported_language_cb()' returns @c false, it should be stopped to call 'stte_supported_language_cb()'.
 * @param[in] callback The callback function
 * @param[in] user_data The user data which must be passed to the callback function 'stte_supported_language_cb()'
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -270,7 +270,7 @@ typedef int (*stte_foreach_supported_langs_cb)(stte_supported_language_cb callba
 * @param[out] is_valid A variable for checking whether the corresponding language is valid or not.
 *                      @c true to be valid,
 *                      @c false to be invalid
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -283,7 +283,7 @@ typedef int (*stte_is_valid_language_cb)(const char* language, bool* is_valid);
 * @brief Called when the engine service user checks whether STT engine supports silence detection.
 * @since_tizen 3.0
 * @remarks This callback function is mandatory and must be registered using stte_main().
-* @return @c true to support silence detection, 
+* @return @c true to support silence detection,
 *         @c false not to support silence detection
 * @see stte_set_silence_detection_cb()
 */
@@ -298,7 +298,7 @@ typedef bool (*stte_support_silence_detection_cb)(void);
 * @param[out] is_supported A variable for checking whether STT engine supports the corresponding recognition type.
 *                          @c true to support recognition type,
 *                          @c false not to support recognition type
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -315,7 +315,7 @@ typedef int (*stte_support_recognition_type_cb)(const char* type, bool* is_suppo
 * @param[out] types The format used by the recorder
 * @param[out] rate The sample rate used by the recorder
 * @param[out] channels The number of channels used by the recorder
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_STATE Not initialized
@@ -331,7 +331,7 @@ typedef int (*stte_get_recording_format_cb)(stte_audio_type_e* types, int* rate,
 * @param[in] is_set A variable for setting the silence detection.
 *                   @c true to detect the silence,
 *                   @c false not to detect the silence
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_STATE Not initialized
@@ -352,7 +352,7 @@ typedef int (*stte_set_silence_detection_cb)(bool is_set);
 * @param[out] is_agreed A variable for checking whether the application agreed to use STT engine or not.
 *                       @c true to agree,
 *                       @c false to disagree
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_STATE Not initialized
@@ -365,7 +365,7 @@ typedef int (*stte_check_app_agreed_cb)(const char* appid, bool* is_agreed);
 * @brief Called when the engine service user checks whether STT engine needs the application's credential.
 * @since_tizen 3.0
 * @remarks This callback function is mandatory and must be registered using stte_main().
-* @return @c true if STT engine needs the application's credential, 
+* @return @c true if STT engine needs the application's credential,
 *         otherwise @c false
 */
 typedef bool (*stte_need_app_credential_cb)(void);
@@ -381,7 +381,7 @@ typedef bool (*stte_need_app_credential_cb)(void);
 * @param[in] time_info The time information
 * @param[in] callback The callback function
 * @param[in] user_data The user data which must be passed to the callback function 'stte_result_time_cb()'
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -406,7 +406,7 @@ typedef int (*stte_foreach_result_time_cb)(void* time_info, stte_result_time_cb
 * @param[in] appid The Application ID
 * @param[in] credential The credential granted to the application
 * @param[in] user_data The user data to be passed to the callback function
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -432,7 +432,7 @@ typedef int (*stte_start_cb)(const char* language, const char* type, const char*
 *          Also, this function should be returned immediately after recording data copy.
 * @param[in] data The recording data
 * @param[in] length The length of recording data
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -452,7 +452,7 @@ typedef int (*stte_set_recording_data_cb)(const void* data, unsigned int length)
 * @details This callback function is called by the engine service user to stop recording and to get the recognition result.
 * @since_tizen 3.0
 * @remarks This callback function is mandatory and must be registered using stte_main().
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_STATE Invalid state
@@ -474,7 +474,7 @@ typedef int (*stte_stop_cb)(void);
 *          Also, when starting the recorder is failed, this function is called.
 * @since_tizen 3.0
 * @remarks This callback function is mandatory and must be registered using stte_main().
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful.
 * @retval #STTE_ERROR_INVALID_STATE Invalid state.
@@ -496,7 +496,7 @@ typedef int (*stte_cancel_cb)(void);
 * @param[out] engine_name Name of engine
 * @param[out] engine_setting The engine setting application(ui app)'s app ID
 * @param[out] use_network A variable for checking whether the network is used or not
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error code on failure
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -512,7 +512,7 @@ typedef int (*stte_get_info_cb)(char** engine_uuid, char** engine_name, char** e
 * @remarks This callback function is optional and is registered using stte_set_private_data_set_cb().
 * @param[in] key The key field of private data
 * @param[in] data The data field of private data
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -530,7 +530,7 @@ typedef int (*stte_private_data_set_cb)(const char* key, const char* data);
 * @remarks This callback function is optional and is registered using stte_set_private_data_requested_cb().
 * @param[out] key The key field of private data
 * @param[out] data The data field of private data
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
 * @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
@@ -597,12 +597,12 @@ typedef struct {
 * @param[in] argc The argument count(original)
 * @param[in] argv The argument(original)
 * @param[in] callback The structure of engine request callback function
-* @return This function returns @c zero on success, 
+* @return This function returns @c zero on success,
 *         or negative with error code on failure
 * @retval #STTE_ERROR_NONE Successful
-* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
-* @retval #STTE_ERROR_PERMISSION_DENIED        Permission denied
 * @retval #STTE_ERROR_NOT_SUPPORTED Not supported
+* @retval #STTE_ERROR_PERMISSION_DENIED Permission denied
+* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
 * @retval #STTE_ERROR_OPERATION_FAILED Operation failure
 * @see stte_request_callback_s
 * @code
@@ -693,7 +693,7 @@ int stte_main(int argc, char** argv, stte_request_callback_s *callback);
 /**
 * @brief Sends the recognition result to the engine service user.
 * @since_tizen 3.0
-* @remarks This API is used in stte_set_recording_data_cb() and stte_stop_cb(), when STT engine sends the recognition result to the engine service user.
+* @remarks This function is used in stte_set_recording_data_cb() and stte_stop_cb(), when STT engine sends the recognition result to the engine service user.
 *          This function is called in the following situations; 1) after stte_stop_cb() is called, 2) the end point of speech is detected from recording, or 3) partial result is occurred.
 *          The recognition result and @a user_data must be transferred to the engine service user through this function.
 *          Also, @a time_info must be transferred to stte_foreach_result_time_cb(). The type of @a time_info is up to the STT engine developer.
@@ -704,12 +704,11 @@ int stte_main(int argc, char** argv, stte_request_callback_s *callback);
 * @param[in] msg Engine message (e.g. #STTE_RESULT_MESSAGE_NONE, #STTE_RESULT_MESSAGE_ERROR_TOO_SHORT)
 * @param[in] time_info The time information
 * @param[in] user_data The user data passed from stte_start_cb()
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
-* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
-* @retval #STTE_ERROR_PERMISSION_DENIED Permission denied
 * @retval #STTE_ERROR_NOT_SUPPORTED Not supported
+* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
 * @retval #STTE_ERROR_OPERATION_FAILED Operation failure
 * @pre The stte_main() function should be invoked before this function is called.
 *      stte_stop_cb() will invoke this function.
@@ -741,12 +740,11 @@ int stte_send_result(stte_result_event_e event, const char* type, const char** r
 * @since_tizen 3.0
 * @param[in] error The error reason
 * @param[in] msg The error message
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
-* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
-* @retval #STTE_ERROR_PERMISSION_DENIED Permission denied
 * @retval #STTE_ERROR_NOT_SUPPORTED Not supported
+* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
 * @retval #STTE_ERROR_OPERATION_FAILED Operation failure
 * @pre The stte_main() function should be invoked before this function is called.
 */
@@ -756,16 +754,15 @@ int stte_send_error(stte_error_e error, const char* msg);
 /**
 * @brief Sends the speech status to the engine service user when STT engine notifies the change of the speech status.
 * @since_tizen 3.0
-* @remarks This API is invoked when STT engine wants to notify the change of the speech status anytime.
-*          NOTE that this API can be invoked for recognizing the speech.
-* @param[in] status The status of speech (e.g. STTE_SPEECH_STATUS_START_POINT_DETECTED or STTE_SPEECH_STATUS_END_POINT_DETECTED)
+* @remarks This function is invoked when STT engine wants to notify the change of the speech status anytime.
+*          NOTE that this function can be invoked for recognizing the speech.
+* @param[in] status The status of speech (e.g. #STTE_SPEECH_STATUS_BEGINNING_POINT_DETECTED or #STTE_SPEECH_STATUS_END_POINT_DETECTED)
 * @param[in] user_data The user data passed from the start function.
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
-* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
-* @retval #STTE_ERROR_PERMISSION_DENIED Permission denied
 * @retval #STTE_ERROR_NOT_SUPPORTED Not supported
+* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
 * @retval #STTE_ERROR_OPERATION_FAILED Operation failure
 * @pre The stte_main() function should be invoked before this function is called.
 *      stte_start_cb() and stte_set_recording_data_cb() will invoke this function.
@@ -782,12 +779,12 @@ int stte_send_speech_status(stte_speech_status_e status, void* user_data);
 * @privilege %http://tizen.org/privilege/recorder
 * @remarks The stte_private_data_set_cb() function is called when the engine service user sends the private data.
 * @param[in] callback_func stte_private_data_set event callback function
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
-* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
-* @retval #STTE_ERROR_PERMISSION_DENIED Permission denied
 * @retval #STTE_ERROR_NOT_SUPPORTED Not supported
+* @retval #STTE_ERROR_PERMISSION_DENIED Permission denied
+* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
 * @retval #STTE_ERROR_OPERATION_FAILED Operation failure
 * @pre The stte_main() function should be invoked before this function is called.
 * @see stte_private_data_set_cb()
@@ -802,12 +799,12 @@ int stte_set_private_data_set_cb(stte_private_data_set_cb callback_func);
 * @privilege %http://tizen.org/privilege/recorder
 * @remarks The stte_private_data_requested_cb() function is called when the engine service user gets the private data from STT engine.
 * @param[in] callback_func stte_private_data_requested event callback function
-* @return @c 0 on success, 
+* @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
-* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
-* @retval #STTE_ERROR_PERMISSION_DENIED Permission denied
 * @retval #STTE_ERROR_NOT_SUPPORTED Not supported
+* @retval #STTE_ERROR_PERMISSION_DENIED Permission denied
+* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
 * @retval #STTE_ERROR_OPERATION_FAILED Operation failure
 * @pre The stte_main() function should be invoked before this function is called.
 * @see stte_private_data_requested_cb()
@@ -824,8 +821,8 @@ int stte_set_private_data_requested_cb(stte_private_data_requested_cb callback_f
 * @return @c 0 on success,
 *         otherwise a negative error value
 * @retval #STTE_ERROR_NONE Successful
-* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
 * @retval #STTE_ERROR_NOT_SUPPORTED Not supported
+* @retval #STTE_ERROR_INVALID_PARAMETER Invalid parameter
 * @retval #STTE_ERROR_OPERATION_FAILED Operation failure
 * @pre The stte_main() function should be invoked before this function is called.
 * @see stte_audio_type_cb()
index 06ab91b..b14edc1 100644 (file)
@@ -57,7 +57,7 @@ typedef enum {
        STTD_ERROR_NO_SPEECH                    = TIZEN_ERROR_STT | 0x06,       /**< No speech while recording */
        STTD_ERROR_RECORDING_TIMED_OUT          = TIZEN_ERROR_STT | 0x10,       /**< Recording timed out */
        STTD_ERROR_SERVICE_RESET                = TIZEN_ERROR_STT | 0x11        /**< Service reset */
-} stt_error_e;
+} sttd_error_e;
 
 typedef enum {
        STTD_RESULT_STATE_DONE          = 0,                    /**< Sync state change */
index c2b1ae1..59caa14 100755 (executable)
 #include <aul.h>
 #include <Ecore.h>
 #include <vconf.h>
+#include <stdatomic.h>
+#include <system_info.h>
+#include <cynara-client.h>
+#include <cynara-error.h>
+#include <cynara-session.h>
+#include <pthread.h>
 
 #include "stt_engine.h"
 #include "stt_defs.h"
 #include "sttd_dbus.h"
 #include "sttd_server.h"
 #include "sttd_engine_agent.h"
+#include "stt_dlog.h"
 
 #include "stte.h"
 
+static atomic_int g_feature_enabled = -1;
+static cynara *p_cynara = NULL;
+static pthread_mutex_t g_cynara_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static bool is_feature_enabled()
+{
+       if (1 == g_feature_enabled) {
+               return true;
+       }
+
+       if (0 == g_feature_enabled) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] TTS feature NOT supported");
+               return false;
+       }
+
+       bool stt_supported = false;
+       if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool(STT_FEATURE_PATH, &stt_supported)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Fail to get feature value");
+               return false;
+       }
+
+       bool mic_supported = false;
+       if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool(STT_MIC_FEATURE_PATH, &mic_supported)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Fail to get feature value");
+               return false;
+       }
+
+       if (false == stt_supported || false == mic_supported) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] STT NOT supported");
+               g_feature_enabled = 0;
+               return false;
+       }
+
+       g_feature_enabled = 1;
+       return true;
+}
+
+static bool initialize_privilege_checker()
+{
+       int ret = cynara_initialize(&p_cynara, NULL);
+       if (CYNARA_API_SUCCESS != ret)
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] fail to initialize"); //LCOV_EXCL_LINE
+
+       return ret == CYNARA_API_SUCCESS;
+}
+
+static bool is_privilege_allowed(const char* uid, const char * privilege)
+{
+       FILE *fp = NULL;
+       char label_path[1024] = "/proc/self/attr/current";
+       char smack_label[1024] = {'\0',};
+
+       if (!p_cynara) {
+               return false;
+       }
+
+       fp = fopen(label_path, "r");
+       if (fp != NULL) {
+               if (0 >= fread(smack_label, 1, sizeof(smack_label), fp))
+
+               fclose(fp);
+       }
+
+       pid_t pid = getpid();
+       char *session = cynara_session_from_pid(pid);
+       int ret = cynara_check(p_cynara, smack_label, session, uid, privilege);
+       free(session);
+
+       if (ret != CYNARA_API_ACCESS_ALLOWED) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Client]cynara_check returned %d(Denied)", ret);
+               return false;
+       }
+       return true;
+}
+
+static void deinitialize_privilege_checker()
+{
+       if (p_cynara)
+               cynara_finish(p_cynara);
+       p_cynara = NULL;
+}
+
+static bool is_stt_privilege_allowed()
+{
+       pthread_mutex_lock(&g_cynara_mutex);
+       bool is_initialized = initialize_privilege_checker();
+       if (false == is_initialized) {
+               pthread_mutex_unlock(&g_cynara_mutex);
+               return false;
+       }
+
+       char uid[16];
+       snprintf(uid, 16, "%d", getuid());
+       bool is_allowed = is_privilege_allowed(uid, STT_PRIVILEGE_RECORDER);
+       deinitialize_privilege_checker();
+       if (false == is_allowed) {
+               pthread_mutex_unlock(&g_cynara_mutex);
+               return false;
+       }
+
+       pthread_mutex_unlock(&g_cynara_mutex);
+       return true;
+}
+
+static inline int check_feature_and_privilege()
+{
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
+       RETV_IF(false == is_stt_privilege_allowed(), STTE_ERROR_PERMISSION_DENIED);
+
+       return STTE_ERROR_NONE;
+}
+
 static bool __is_default_engine()
 {
        char* engine = NULL;
@@ -50,8 +169,11 @@ static bool __is_default_engine()
 int stte_main(int argc, char**argv, stte_request_callback_s *callback)
 {
        SLOG(LOG_DEBUG, TAG_STTD, "===== Start engine");
-
-       int ret = STTE_ERROR_NONE;
+       int ret = check_feature_and_privilege();
+       if (STTE_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "Precondition is not met (%s)", get_error_message(ret));
+               return ret;
+       }
 
        if (!ecore_init()) {
                SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Fail to initialize Ecore");
@@ -88,13 +210,14 @@ int stte_main(int argc, char**argv, stte_request_callback_s *callback)
 int stte_send_result(stte_result_event_e event, const char* type, const char** result, int result_count,
                                const char* msg, void* time_info, void* user_data)
 {
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
+
        if (NULL == type || NULL == result) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Invalid parameter");
        }
 
-       int ret = STTE_ERROR_NONE;
        stt_engine_result_cb result_cb = NULL;
-       ret = stt_engine_get_recognition_result_cb(&result_cb);
+       int ret = stt_engine_get_recognition_result_cb(&result_cb);
        if (STTE_ERROR_NONE == ret && NULL != result_cb) {
                ret = result_cb(event, type, result, result_count, msg, time_info, user_data);
        } else {
@@ -109,8 +232,9 @@ int stte_send_result(stte_result_event_e event, const char* type, const char** r
 
 int stte_send_error(stte_error_e error, const char* msg)
 {
-       int ret = STTE_ERROR_NONE;
-       ret = sttd_engine_agent_send_error(error, msg);
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
+
+       int ret = sttd_engine_agent_send_error(error, msg);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send error info");
        }
@@ -119,8 +243,9 @@ int stte_send_error(stte_error_e error, const char* msg)
 
 int stte_send_speech_status(stte_speech_status_e status, void* user_data)
 {
-       int ret = STTE_ERROR_NONE;
-       ret = sttd_engine_agent_send_speech_status(status, user_data);
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
+
+       int ret = sttd_engine_agent_send_speech_status(status, user_data);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send speech status");
        }
@@ -129,7 +254,12 @@ int stte_send_speech_status(stte_speech_status_e status, void* user_data)
 
 int stte_set_private_data_set_cb(stte_private_data_set_cb callback)
 {
-       int ret = STTE_ERROR_NONE;
+       int ret = check_feature_and_privilege();
+       if (STTE_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "Precondition is not met (%s)", get_error_message(ret));
+               return ret;
+       }
+
        ret = stt_engine_set_private_data_set_cb(callback, NULL);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set private data set callback");
@@ -139,7 +269,12 @@ int stte_set_private_data_set_cb(stte_private_data_set_cb callback)
 
 int stte_set_private_data_requested_cb(stte_private_data_requested_cb callback)
 {
-       int ret = STTE_ERROR_NONE;
+       int ret = check_feature_and_privilege();
+       if (STTE_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "Precondition is not met (%s)", get_error_message(ret));
+               return ret;
+       }
+
        ret = stt_engine_set_private_data_requested_cb(callback, NULL);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set private data requested callback");
@@ -150,9 +285,9 @@ int stte_set_private_data_requested_cb(stte_private_data_requested_cb callback)
 int stte_set_audio_type_set_cb(stte_audio_type_cb callback, void* user_data)
 {
        SLOG(LOG_INFO, TAG_STTD, "[Server Info] Set audio type set callback");
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
 
-       int ret = STTE_ERROR_NONE;
-       ret = stt_engine_set_audio_type_set_cb(callback, user_data);
+       int ret = stt_engine_set_audio_type_set_cb(callback, user_data);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set audio type set");
        }
@@ -162,9 +297,9 @@ int stte_set_audio_type_set_cb(stte_audio_type_cb callback, void* user_data)
 int stte_unset_audio_type_set_cb(void)
 {
        SLOG(LOG_INFO, TAG_STTD, "[Server Info] Unset audio type set callback");
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
 
-       int ret = STTE_ERROR_NONE;
-       ret = stt_engine_unset_audio_type_set_cb();
+       int ret = stt_engine_unset_audio_type_set_cb();
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to unset audio type set");
        }