* @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
* @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
* 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
* @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
* @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()
*/
* @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
* @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
* @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
* @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
* @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);
* @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
* @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
* 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
* @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
* 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.
* @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
* @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
* @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
* @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
/**
* @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.
* @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.
* @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.
*/
/**
* @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.
* @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()
* @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()
* @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()
#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;
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");
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 {
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");
}
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");
}
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");
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");
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");
}
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");
}