From 5fb5703670aee7ec524a7f4627a1a79d49fb274c Mon Sep 17 00:00:00 2001 From: ulgal-park Date: Mon, 13 Mar 2023 12:54:05 +0900 Subject: [PATCH 01/16] add guard clause when use g_VoiceControlClients Change-Id: I36d7c0cccd8cee52a6948cbcf3af873e3ae950b9 --- common/vc_config_mgr.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/vc_config_mgr.cpp b/common/vc_config_mgr.cpp index 23a1fd1..e502e7e 100644 --- a/common/vc_config_mgr.cpp +++ b/common/vc_config_mgr.cpp @@ -105,6 +105,11 @@ static void notify_language_changed(const char* before_lang, const char* current return; } + if (nullptr == g_VoiceControlClients) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist"); + return; + } + auto clients = g_VoiceControlClients->getClients(); for (auto &clientInfo : clients) { if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { -- 2.7.4 From 21d4d7f5d04f839b0cf97cdb6c5d5701ff92d64b Mon Sep 17 00:00:00 2001 From: ulgal-park Date: Mon, 13 Mar 2023 12:54:48 +0900 Subject: [PATCH 02/16] Update version to 1.75.1 Change-Id: Id348d0e8a8c010910bd274f455133c499906f48b --- packaging/voice-control.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index db9e989..ce6a942 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -1,6 +1,6 @@ Name: voice-control Summary: Voice control client library and daemon -Version: 1.75.0 +Version: 1.75.1 Release: 1 Group: Graphics & UI Framework/Voice Framework License: Apache-2.0 -- 2.7.4 From 50c7766f821535255f2c22b79cce0a1774bdf9ff Mon Sep 17 00:00:00 2001 From: sooyeon Date: Tue, 14 Mar 2023 14:50:47 +0900 Subject: [PATCH 03/16] Fix Svace issues by removing unused codes Change-Id: I4b6d194faacd074305ab7a6968c715e94d0994ba Signed-off-by: sooyeon --- client/CMakeLists.txt | 1 - client/vc_mgr.c | 35 +---- client/vc_mgr_player.c | 413 ------------------------------------------------- client/vc_mgr_player.h | 25 --- 4 files changed, 2 insertions(+), 472 deletions(-) delete mode 100644 client/vc_mgr_player.c delete mode 100644 client/vc_mgr_player.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 6c62f69..0195eb3 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -56,7 +56,6 @@ SET(MANAGER_SRCS vc_mgr_core.c vc_mgr_client.c vc_mgr_data.cpp - vc_mgr_player.c vc_mgr_tidl.c vc_mgr_proxy.c vc_mgr_stub.c diff --git a/client/vc_mgr.c b/client/vc_mgr.c index 72f264b..2fc2d44 100644 --- a/client/vc_mgr.c +++ b/client/vc_mgr.c @@ -32,7 +32,6 @@ #include "vc_mgr_client.h" #include "vc_mgr_tidl.h" #include "vc_mgr_data.h" -#include "vc_mgr_player.h" #include "vc_mgr_ducking.h" #include "voice_control_command.h" #include "voice_control_command_expand.h" @@ -293,13 +292,6 @@ int vc_mgr_initialize(void) return ret; } - /* for TTS feedback */ -/* ret = vc_mgr_player_init(); - if (0 != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to initialize VC mgr player : %d", ret); - } -*/ - ret = vc_mgr_ducking_create(); if (VC_ERROR_NONE != ret) { SLOG(LOG_INFO, TAG_VCM, "[INFO] Fail to ducking create : %d", ret); @@ -382,13 +374,6 @@ int vc_mgr_deinitialize(void) SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to finalize DB, ret(%d)", ret); } - /* for TTS feedback */ -/* ret = vc_mgr_player_release(); - if (0 != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to release VC mgr player(%d)", ret); - } -*/ - ret = vc_mgr_ducking_destroy(); if (VC_ERROR_NONE != ret) { SLOG(LOG_INFO, TAG_VCM, "[INFO] Fail to ducking destroy : %d", ret); @@ -2750,20 +2735,12 @@ int vc_mgr_start_feedback(void) /* check state */ RETVM_IF(VC_STATE_READY != state, VC_ERROR_INVALID_STATE, TAG_VCM, "[ERROR] Start feedback : Current state is not 'Ready' (%d)", state); -#if 1 bool is_exist = ecore_thread_check(g_feedback_thread); if (NULL == g_feedback_thread || TRUE == is_exist) { SLOG(LOG_INFO, TAG_VCM, "[INFO] ecore thread run : __tts_feedback_thread"); g_feedback_thread = ecore_thread_run(__tts_feedback_thread, __end_tts_feedback_thread, __cancel_tts_feedback_thread, NULL); } -#else - /* start playing TTS feedback */ - int ret = -1; - ret = vc_mgr_player_play(); - if (0 != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to player play, ret(%d)", ret); - } -#endif + return VC_ERROR_NONE; } @@ -2787,7 +2764,6 @@ int vc_mgr_stop_feedback(void) /* check state */ RETVM_IF(VC_STATE_READY != state, VC_ERROR_INVALID_STATE, TAG_VCM, "[ERROR] Stop feedback : Current state is not 'Ready' (%d)", state); -#if 1 if (g_feedback_thread) { ecore_thread_cancel(g_feedback_thread); g_feedback_thread = NULL; @@ -2810,14 +2786,7 @@ int vc_mgr_stop_feedback(void) break; } } -#else - /* request to stop playing TTS feedback */ - int ret = -1; - ret = vc_mgr_player_stop(); - if (0 != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to player stop, ret(%d)", ret); - } -#endif + return ret; } diff --git a/client/vc_mgr_player.c b/client/vc_mgr_player.c deleted file mode 100644 index 5bfd5be..0000000 --- a/client/vc_mgr_player.c +++ /dev/null @@ -1,413 +0,0 @@ -/* -* Copyright (c) 2018 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 -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an AS IS BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include -#include -#include -#include -#include - -#include "vc_main.h" -#include "vc_mgr_player.h" -#include "vc_mgr_data.h" - -typedef enum { - AUDIO_STATE_NONE = 0, - AUDIO_STATE_READY, - AUDIO_STATE_PLAY -} audio_state_e; - -typedef struct { - vc_feedback_state_e state; - - vc_feedback_event_e event; - int idx; -} player_s; - -#define SOUND_BUFFER_LENGTH 2048 - -static bool g_player_init = false; - -static player_s* g_playing_info; - -static audio_state_e g_audio_state; - -static vc_audio_type_e g_audio_type; - -static vc_audio_channel_e g_audio_channel; - -static int g_sampling_rate; - -static audio_out_h g_audio_h; - - -static int __create_audio_out(int rate, vc_audio_channel_e channel, vc_audio_type_e audio_type) -{ - int ret = -1; - audio_channel_e sample_channel = 0; - audio_sample_type_e sample_type = 0; - - if (VC_AUDIO_CHANNEL_MONO == channel) { - sample_channel = AUDIO_CHANNEL_MONO; - } else if (VC_AUDIO_CHANNEL_STEREO == channel) { - sample_channel = AUDIO_CHANNEL_STEREO; - } - - if (VC_AUDIO_TYPE_PCM_S16_LE == audio_type) { - sample_type = AUDIO_SAMPLE_TYPE_S16_LE; - } else { - sample_type = AUDIO_SAMPLE_TYPE_U8; - } - - /* create audio_out new */ - ret = audio_out_create_new(rate, sample_channel, sample_type, &g_audio_h); - if (AUDIO_IO_ERROR_NONE != ret) { - g_audio_state = AUDIO_STATE_NONE; - g_audio_h = NULL; - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to create audio. ret(%d)", ret); - return -1; - } else { - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Create audio"); - } - - g_audio_channel = channel; - g_audio_type = audio_type; - g_sampling_rate = rate; - - g_audio_state = AUDIO_STATE_READY; - - return 0; -} - -static int __destroy_audio_out() -{ - if (NULL == g_audio_h) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Current handle is not valid"); - return -1; - } - - int ret = -1; - ret = audio_out_destroy(g_audio_h); - if (AUDIO_IO_ERROR_NONE != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to destroy audio. ret(%d)", ret); - return -1; - } else { - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Destroy audio"); - } - - g_audio_channel = 0; - g_audio_type = 0; - g_sampling_rate = 0; - - g_audio_state = AUDIO_STATE_NONE; - g_audio_h = NULL; - - return 0; -} - -int vc_mgr_player_init(int rate, vc_audio_channel_e channel, vc_audio_type_e audio_type) -{ - g_audio_state = AUDIO_STATE_NONE; - g_audio_h = NULL; - - ecore_thread_max_set(1); - - int ret = -1; - - - ret = __create_audio_out(rate, channel, audio_type); - if (0 != ret) { - return VC_ERROR_OPERATION_FAILED; - } - - g_player_init = true; - - return VC_ERROR_NONE; -} - -int vc_mgr_player_release() -{ - if (false == g_player_init) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Not initialized"); - return VC_ERROR_OPERATION_FAILED; - } - - int ret = -1; - - int thread_count = ecore_thread_active_get(); - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Active thread count : %d", thread_count); - int count = 0; - while (0 < thread_count) { - usleep(10000); - - count++; - if (20 == count) { - SLOG(LOG_WARN, TAG_VCM, "[Player WARN] Thread is blocked. Player release continue"); - break; - } - - thread_count = ecore_thread_active_get(); - } - - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Thread is release"); - - ret = __destroy_audio_out(); - if (0 != ret) { - return VC_ERROR_OPERATION_FAILED; - } - - g_player_init = false; - - return VC_ERROR_NONE; -} - -static void __play_feedback_thread(void* data, Ecore_Thread* thread) -{ - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Start thread"); - - if (NULL == g_playing_info) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] No current player"); - return; - } - - player_s* player = g_playing_info; - vc_feedback_data_s* feedback_data = NULL; - - int ret = -1; - int len = SOUND_BUFFER_LENGTH; - int idx = 0; - - while (1) { - /* get feedback data */ - ret = vc_mgr_data_get_feedback_data(&feedback_data); - if (0 != ret || NULL == feedback_data) { - /* empty queue */ - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] No feedback data. Waiting mode"); - - /* waiting */ - while (1) { - usleep(10000); - if (0 < vc_mgr_data_get_feedback_data_size()) { - SLOG(LOG_INFO, TAG_VCM, "[Player INFO] Resume thread"); - break; - } - - if (AUDIO_STATE_PLAY == g_audio_state) { - /* release audio & recover session */ - ret = audio_out_unprepare(g_audio_h); - if (AUDIO_IO_ERROR_NONE != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to unprepare audio"); - } else { - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Unprepare audio"); - } - g_audio_state = AUDIO_STATE_READY; - } - } - - SLOG(LOG_INFO, TAG_VCM, "[Player INFO] Finish to wait for new feedback data come"); - - /* resume play thread */ - player->state = VC_FEEDBACK_STATE_PLAYING; - continue; - } - - if (VC_FEEDBACK_EVENT_START == feedback_data->event || - (VC_FEEDBACK_EVENT_FINISH == player->event && VC_FEEDBACK_EVENT_FINISH == feedback_data->event)) { - int pid = vc_mgr_data_get_pid(); - SLOG(LOG_INFO, TAG_VCM, "[Player DEBUG] Start utterance (%d)", pid); - } - - player->event = feedback_data->event; - idx = 0; - /* If no feedback data and EVENT_FINISH */ - if (NULL == feedback_data->data || 0 >= feedback_data->data_size) { - if (VC_FEEDBACK_EVENT_FINISH == feedback_data->event) { - int pid = vc_mgr_data_get_pid(); - if (pid <= 0) { - return; - } - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] No sound data"); - } - SLOG(LOG_INFO, TAG_VCM, "[Player INFO] Finish utterance"); - vc_mgr_data_clear_feedback_data(&feedback_data); - continue; - } - - if (g_sampling_rate != feedback_data->rate || g_audio_type != feedback_data->audio_type || g_audio_channel != feedback_data->channel) { - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] change audio handle"); - if (NULL != g_audio_h) { - __destroy_audio_out(); - } - - if (0 > __create_audio_out(feedback_data->rate, feedback_data->channel, feedback_data->audio_type)) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to create audio out"); - vc_mgr_data_clear_feedback_data(&feedback_data); - - return; - } - } - - while (VC_FEEDBACK_STATE_PLAYING == player->state) { - if ((unsigned int)idx >= feedback_data->data_size) - break; - - if ((unsigned int)idx + SOUND_BUFFER_LENGTH > feedback_data->data_size) { - len = feedback_data->data_size - idx; - } else { - len = SOUND_BUFFER_LENGTH; - } - - if (AUDIO_STATE_READY == g_audio_state) { - /* request prepare */ - ret = audio_out_prepare(g_audio_h); - if (AUDIO_IO_ERROR_NONE != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to prepare audio"); - vc_mgr_data_clear_feedback_data(&feedback_data); - return; - } - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Prepare audio"); - g_audio_state = AUDIO_STATE_PLAY; - } - - char* temp_data = feedback_data->data; - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] data(%p), idx(%d), len(%d)", temp_data, idx, len); - - ret = audio_out_write(g_audio_h, &temp_data[idx], len); - if (0 > ret) { - SLOG(LOG_WARN, TAG_VCM, "[Player WARN] Fail to audio write - %d", ret); - } else { - idx += len; - } - - if (NULL == g_playing_info) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Current player is NULL"); - g_audio_state = AUDIO_STATE_READY; - ret = audio_out_unprepare(g_audio_h); - if (AUDIO_IO_ERROR_NONE != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to unprepare audio"); - } - - vc_mgr_data_clear_feedback_data(&feedback_data); - - return; - } - } - - if (NULL == g_playing_info && VC_FEEDBACK_STATE_READY == player->state) { - /* player stop */ - g_audio_state = AUDIO_STATE_READY; - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Stop play thread"); - - /* request to unprepare audio */ - ret = audio_out_unprepare(g_audio_h); - if (AUDIO_IO_ERROR_NONE != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to unprepare audio"); - } else { - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Unprepare audio"); - } - - vc_mgr_data_clear_feedback_data(&feedback_data); - return; - } - - if ((VC_FEEDBACK_STATE_PLAYING == player->state) && (VC_FEEDBACK_EVENT_FINISH == feedback_data->event)) { - int pid = vc_mgr_data_get_pid(); - if (pid <= 0) { - return; - } - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] Finish utterance"); - } - - vc_mgr_data_clear_feedback_data(&feedback_data); - - if (NULL == g_playing_info) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Current player is NULL"); - g_audio_state = AUDIO_STATE_READY; - ret = audio_out_unprepare(g_audio_h); - if (AUDIO_IO_ERROR_NONE != ret) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Fail to unprepare audio"); - } - - return; - } - - } - -} - -static void __end_play_feedback_thread(void* data, Ecore_Thread* thread) -{ - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] End thread"); -} - -int vc_mgr_player_play() -{ - if (false == g_player_init) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Not initialized"); - return VC_ERROR_OPERATION_FAILED; - } - - if (NULL != g_playing_info) { - SLOG(LOG_WARN, TAG_VCM, "[Player WARN] Stop old player"); - vc_mgr_player_stop(); - } - - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] start play"); - - /* check sound queue size */ - int data_size = vc_mgr_data_get_feedback_data_size(); - if (0 == data_size) { - SLOG(LOG_WARN, TAG_VCM, "[Player WARN] A sound queue of current player is empty"); - } else if (0 < data_size) { - SLOG(LOG_INFO, TAG_VCM, "[Player INFO] Run thread"); - ecore_thread_run(__play_feedback_thread, __end_play_feedback_thread, NULL, NULL); - } - - return VC_ERROR_NONE; -} - -int vc_mgr_player_stop() -{ - if (false == g_player_init) { - SLOG(LOG_ERROR, TAG_VCM, "[Player ERROR] Not initialized"); - return VC_ERROR_OPERATION_FAILED; - } - - if (NULL != g_playing_info) { - g_playing_info = NULL; - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] No more current playing"); - } - - SLOG(LOG_DEBUG, TAG_VCM, "[Player DEBUG] stop play"); - - int thread_count = ecore_thread_active_get(); - int count = 0; - - while (0 < thread_count) { - usleep(10000); - - count++; - if (30 == count) { - SLOG(LOG_WARN, TAG_VCM, "[Player WARN] Thread is blocked. Player release continue"); - break; - } - - thread_count = ecore_thread_active_get(); - } - - return VC_ERROR_NONE; -} diff --git a/client/vc_mgr_player.h b/client/vc_mgr_player.h deleted file mode 100644 index 6cf550c..0000000 --- a/client/vc_mgr_player.h +++ /dev/null @@ -1,25 +0,0 @@ - -#ifndef __VC_MGR_PLAYER_H__ -#define __VC_MGR_PLAYER_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int vc_mgr_player_init(int rate, vc_audio_channel_e channel, vc_audio_type_e audio_type); - -int vc_mgr_player_release(); - -int vc_mgr_player_play(); - -int vc_mgr_player_stop(); - - -#ifdef __cplusplus -} -#endif - -#endif /* __VC_MGR_PLAYER_H__ */ -- 2.7.4 From 346d4ee111f2b2c517a46858a9b0a5604275c743 Mon Sep 17 00:00:00 2001 From: sooyeon Date: Tue, 14 Mar 2023 15:06:56 +0900 Subject: [PATCH 04/16] Update version (1.75.2) Change-Id: I6ab67a569f0ebf740037bb74aaf6d1075fd3a9f0 Signed-off-by: sooyeon --- packaging/voice-control.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index ce6a942..d10e747 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -1,6 +1,6 @@ Name: voice-control Summary: Voice control client library and daemon -Version: 1.75.1 +Version: 1.75.2 Release: 1 Group: Graphics & UI Framework/Voice Framework License: Apache-2.0 -- 2.7.4 From b6945fa0b3451bf8fc9f3132b2d9ae19d14e5ebb Mon Sep 17 00:00:00 2001 From: ulgal-park Date: Tue, 14 Mar 2023 21:19:13 +0900 Subject: [PATCH 05/16] add guard clause when use tidl info Change-Id: If1b530d30def44840a7f56238bab420bcc65f5fd --- client/vc_mgr_tidl.c | 6 ++++++ client/vc_widget_tidl.c | 6 ++++++ server/vcd_tidl.c | 15 +++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/client/vc_mgr_tidl.c b/client/vc_mgr_tidl.c index 4d1937c..a4cec35 100644 --- a/client/vc_mgr_tidl.c +++ b/client/vc_mgr_tidl.c @@ -277,6 +277,8 @@ static void __send_buffer_cb(void *user_data, rpc_port_proxy_vc_mgr_proxy_array_ static void __on_connected(rpc_port_proxy_vc_mgr_proxy_vc_mgr_h h, void *user_data) { + RETM_IF(NULL == g_proxy_tidl_info, TAG_VCM, "[ERROR] Fail to get tidl info"); + g_proxy_tidl_info->connected = true; g_proxy_tidl_info->connection_requesting = false; g_proxy_tidl_info->register_callback_invoked = false; @@ -286,6 +288,8 @@ static void __on_connected(rpc_port_proxy_vc_mgr_proxy_vc_mgr_h h, void *user_da static void __on_disconnected(rpc_port_proxy_vc_mgr_proxy_vc_mgr_h h, void *user_data) { + RETM_IF(NULL == g_proxy_tidl_info, TAG_VCM, "[ERROR] Fail to get tidl info"); + g_proxy_tidl_info->connected = false; g_proxy_tidl_info->connection_requesting = false; g_proxy_tidl_info->register_callback_invoked = false; @@ -297,6 +301,8 @@ static void __on_disconnected(rpc_port_proxy_vc_mgr_proxy_vc_mgr_h h, void *user static void __on_rejected(rpc_port_proxy_vc_mgr_proxy_vc_mgr_h h, void *user_data) { + RETM_IF(NULL == g_proxy_tidl_info, TAG_VCM, "[ERROR] Fail to get tidl info"); + g_proxy_tidl_info->connection_requesting = false; g_proxy_tidl_info->register_callback_invoked = false; diff --git a/client/vc_widget_tidl.c b/client/vc_widget_tidl.c index d6fbbc9..b099088 100644 --- a/client/vc_widget_tidl.c +++ b/client/vc_widget_tidl.c @@ -144,6 +144,8 @@ static void __notify_cb(void *user_data, bundle *msg) static void __on_connected(rpc_port_proxy_vc_widget_proxy_vc_widget_h h, void *user_data) { + RETM_IF(NULL == g_proxy_tidl_info, TAG_VCW, "[ERROR] Fail to get tidl info"); + g_proxy_tidl_info->connected = true; g_proxy_tidl_info->connection_requesting = false; g_proxy_tidl_info->register_callback_invoked = false; @@ -153,6 +155,8 @@ static void __on_connected(rpc_port_proxy_vc_widget_proxy_vc_widget_h h, void *u static void __on_disconnected(rpc_port_proxy_vc_widget_proxy_vc_widget_h h, void *user_data) { + RETM_IF(NULL == g_proxy_tidl_info, TAG_VCW, "[ERROR] Fail to get tidl info"); + g_proxy_tidl_info->connected = false; g_proxy_tidl_info->connection_requesting = false; g_proxy_tidl_info->register_callback_invoked = false; @@ -164,6 +168,8 @@ static void __on_disconnected(rpc_port_proxy_vc_widget_proxy_vc_widget_h h, void static void __on_rejected(rpc_port_proxy_vc_widget_proxy_vc_widget_h h, void *user_data) { + RETM_IF(NULL == g_proxy_tidl_info, TAG_VCW, "[ERROR] Fail to get tidl info"); + g_proxy_tidl_info->connection_requesting = false; g_proxy_tidl_info->register_callback_invoked = false; diff --git a/server/vcd_tidl.c b/server/vcd_tidl.c index 0940cd0..bef79d8 100644 --- a/server/vcd_tidl.c +++ b/server/vcd_tidl.c @@ -1378,6 +1378,11 @@ static void __widget_on_connected(rpc_port_proxy_vcd_widget_proxy_vcd_widget_h h int pid = (intptr_t)user_data; widget_tidl_info_s* widget_tidl_info = vcd_client_widget_get_tidl_info(pid); + if (NULL == widget_tidl_info) { + SLOG(LOG_ERROR, TAG_VCD, "[TIDL] tidl proxy info not allocated"); + return; + } + widget_tidl_info->connected = true; widget_tidl_info->connection_requesting = false; @@ -1389,6 +1394,11 @@ static void __widget_on_disconnected(rpc_port_proxy_vcd_widget_proxy_vcd_widget_ int pid = (intptr_t)user_data; widget_tidl_info_s* widget_tidl_info = vcd_client_widget_get_tidl_info(pid); + if (NULL == widget_tidl_info) { + SLOG(LOG_ERROR, TAG_VCD, "[TIDL] tidl proxy info not allocated"); + return; + } + widget_tidl_info->connected = false; widget_tidl_info->connection_requesting = false; @@ -1400,6 +1410,11 @@ static void __widget_on_rejected(rpc_port_proxy_vcd_widget_proxy_vcd_widget_h h, int pid = (intptr_t)user_data; widget_tidl_info_s* widget_tidl_info = vcd_client_widget_get_tidl_info(pid); + if (NULL == widget_tidl_info) { + SLOG(LOG_ERROR, TAG_VCD, "[TIDL] tidl proxy info not allocated"); + return; + } + widget_tidl_info->connection_requesting = false; SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Rejected from widget"); -- 2.7.4 From 98b772f4324cd5483a346a882ea3c346de60d1a7 Mon Sep 17 00:00:00 2001 From: ulgal-park Date: Tue, 14 Mar 2023 21:26:44 +0900 Subject: [PATCH 06/16] Update version to 1.75.3 Change-Id: Ide3c6b0833559c11759c1afccb3a846eaba642f1 --- packaging/voice-control.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index d10e747..39f30d7 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -1,6 +1,6 @@ Name: voice-control Summary: Voice control client library and daemon -Version: 1.75.2 +Version: 1.75.3 Release: 1 Group: Graphics & UI Framework/Voice Framework License: Apache-2.0 -- 2.7.4 From 3da5984f05918108d467f56f3eba214e4e1f7260 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Tue, 4 Apr 2023 18:16:17 +0900 Subject: [PATCH 07/16] Unregister TIDL stub port when connection is closed - Issue: Connected event callback is invoked even though the connection is closed. - Solution: Previous code does not invoke unregister method of TIDL stub, so the connection callback still can be invoked even if the client succeeds to deinitialize. And this is no intended behavior, so this patch fixes this behaivor. Through this patch, widget module will properly call unregister method. And also, widget module will check first if the stub information is valid. Change-Id: I1864824237218468b5341eb32c23c17e9f278651 Signed-off-by: Suyeon Hwang --- client/vc_widget_tidl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/client/vc_widget_tidl.c b/client/vc_widget_tidl.c index b099088..55b2e09 100644 --- a/client/vc_widget_tidl.c +++ b/client/vc_widget_tidl.c @@ -197,6 +197,8 @@ static rpc_port_proxy_vc_widget_proxy_vc_widget_h __create_rpc_port(const char* static void __vcd_widget_create_cb(rpc_port_stub_vc_widget_stub_vcd_widget_context_h context, void *user_data) { + RETM_IF(NULL == g_stub_tidl_info, TAG_VCW, "[ERROR] Fail to get tidl stub info"); + g_stub_tidl_info->connected = true; g_stub_tidl_info->register_callback_requesting = false; @@ -216,6 +218,8 @@ static void __vcd_widget_create_cb(rpc_port_stub_vc_widget_stub_vcd_widget_conte static void __vcd_widget_terminate_cb(rpc_port_stub_vc_widget_stub_vcd_widget_context_h context, void *user_data) { + RETM_IF(NULL == g_stub_tidl_info, TAG_VCW, "[ERROR] Fail to get tidl stub info"); + g_stub_tidl_info->connected = false; g_stub_tidl_info->register_callback_requesting = false; @@ -243,6 +247,8 @@ static int __vcd_widget_asr_result_cb(rpc_port_stub_vc_widget_stub_vcd_widget_co static void __register_stub_callback() { + RETM_IF(NULL == g_stub_tidl_info, TAG_VCW, "[TIDL ERROR] g_stub_tidl_info is not allocated"); + if (g_stub_tidl_info->register_callback_requesting) { return; } @@ -344,6 +350,12 @@ int vc_widget_tidl_close_connection() free(g_proxy_tidl_info); g_proxy_tidl_info = NULL; + if (0 != rpc_port_stub_vc_widget_stub_vcd_widget_unregister()) { + SLOG(LOG_ERROR, TAG_VCW, "[TIDL ERROR] Fail to unregister stub"); + pthread_mutex_unlock(&g_w_tidl_mutex); + return VC_ERROR_OPERATION_FAILED; + } + free(g_stub_tidl_info); g_stub_tidl_info = NULL; -- 2.7.4 From b8511f431544f16a05aad1bf87658e00fb38f6cb Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Tue, 4 Apr 2023 18:24:07 +0900 Subject: [PATCH 08/16] Update version (1.75.4) Change-Id: Ibd6321eb00b938a8811e031bee00469c62e3a85d Signed-off-by: Suyeon Hwang --- packaging/voice-control.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index 39f30d7..467a94a 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -1,6 +1,6 @@ Name: voice-control Summary: Voice control client library and daemon -Version: 1.75.3 +Version: 1.75.4 Release: 1 Group: Graphics & UI Framework/Voice Framework License: Apache-2.0 -- 2.7.4 From 18b00a7cc7518a781638a7751523824d8578f3dc Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Thu, 6 Apr 2023 14:09:29 +0900 Subject: [PATCH 09/16] Rearrange the scope of each temporary variables This patch is for solving static analysis issues. Through this patch, the scope of each temporary variables will become as smaller as they can. This change can reduce the possibility of mistakes such as accessing invalid pointer. Change-Id: I93aaef1711ddc27663812fd0c089c9be4c277f23 Signed-off-by: Suyeon Hwang --- common/vc_cmd_db.c | 8 +++----- common/vc_command.c | 11 ++++------- server/vcd_client_data.c | 7 ++----- server/vcd_server.c | 13 ++++--------- 4 files changed, 13 insertions(+), 26 deletions(-) diff --git a/common/vc_cmd_db.c b/common/vc_cmd_db.c index 2ddbb47..9a30848 100644 --- a/common/vc_cmd_db.c +++ b/common/vc_cmd_db.c @@ -2172,12 +2172,10 @@ static int __vc_db_insert_command(sqlite3* db_handle, int pid, vc_cmd_type_e typ } if (0 != g_slist_length(cmd_list)) { - GSList *iter = NULL; - char* temp_command = NULL; - iter = g_slist_nth(cmd_list, 0); + GSList *iter = g_slist_nth(cmd_list, 0); while (NULL != iter) { - temp_command = iter->data; + char *temp_command = iter->data; if (NULL != temp_command) { if (NULL != tmp_cmd->command) { @@ -2219,7 +2217,7 @@ static int __vc_db_insert_command(sqlite3* db_handle, int pid, vc_cmd_type_e typ if (VC_DB_ERROR_NONE != ret) { while (NULL != iter) { - temp_command = iter->data; + char *temp_command = iter->data; if (NULL != temp_command) { cmd_list = g_slist_remove(cmd_list, temp_command); diff --git a/common/vc_command.c b/common/vc_command.c index 1c63b22..e6b5767 100644 --- a/common/vc_command.c +++ b/common/vc_command.c @@ -1763,8 +1763,6 @@ static int __vc_cmd_trelative_check(const char *str, struct tm *td, int *exist) int hour = -1; int min = -1; - char *tempstr = NULL; - *exist = 0; ret = regexec(®[3], str, 1, pmatch, 0); if (0 == ret) { @@ -1782,7 +1780,7 @@ static int __vc_cmd_trelative_check(const char *str, struct tm *td, int *exist) SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid string length"); return VC_ERROR_OPERATION_FAILED; } - tempstr = strndup(str + pmatch[1].rm_so, (size_t)len); + char *tempstr = strndup(str + pmatch[1].rm_so, (size_t)len); if (NULL == tempstr) { SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); @@ -1808,7 +1806,7 @@ static int __vc_cmd_trelative_check(const char *str, struct tm *td, int *exist) SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid string length"); return VC_ERROR_OPERATION_FAILED; } - tempstr = strndup(str + pmatch[1].rm_so, (size_t)len); + char *tempstr = strndup(str + pmatch[1].rm_so, (size_t)len); if (NULL == tempstr) { SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); @@ -1861,7 +1859,6 @@ static int __vc_cmd_tabsolute_check(const char *str, struct tm *td, int *exist) int min = -1; int sidx = -1; int eidx = -1; - char *tempstr = NULL; *exist = 0; ret = regexec(®[0], str, 5, pmatch, 0); @@ -1882,7 +1879,7 @@ static int __vc_cmd_tabsolute_check(const char *str, struct tm *td, int *exist) SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid string length"); return VC_ERROR_OPERATION_FAILED; } - tempstr = strndup(str + pmatch[1].rm_so, (size_t)len); + char *tempstr = strndup(str + pmatch[1].rm_so, (size_t)len); if (NULL == tempstr) { SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); @@ -1922,7 +1919,7 @@ static int __vc_cmd_tabsolute_check(const char *str, struct tm *td, int *exist) idx = 1; len = pmatch[idx].rm_eo - pmatch[idx].rm_so; if (0 < len) { - tempstr = strndup(str + pmatch[idx].rm_so, (size_t)len); + char *tempstr = strndup(str + pmatch[idx].rm_so, (size_t)len); if (NULL == tempstr) { SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); diff --git a/server/vcd_client_data.c b/server/vcd_client_data.c index de4c8cf..ab42c56 100644 --- a/server/vcd_client_data.c +++ b/server/vcd_client_data.c @@ -396,13 +396,10 @@ manager_tidl_info_s* vcd_client_manager_get_tidl_info() static void __vcd_client_release_each_commands(GSList** cmds) { - GSList *iter = NULL; - vc_cmd_s* temp_cmd; - if (0 < g_slist_length(*cmds)) { - iter = g_slist_nth(*cmds, 0); + GSList *iter = g_slist_nth(*cmds, 0); while (NULL != iter) { - temp_cmd = iter->data; + vc_cmd_s *temp_cmd = iter->data; if (NULL != temp_cmd) { if (NULL != temp_cmd->command) { diff --git a/server/vcd_server.c b/server/vcd_server.c index ebdfaf8..9945e0c 100644 --- a/server/vcd_server.c +++ b/server/vcd_server.c @@ -342,12 +342,9 @@ static bool __vcd_launch_app(const char* result) if (0 != g_slist_length(app_list)) { /* release data */ - GSList *iter = NULL; - vc_deactivated_app_s* temp_app = NULL; - iter = g_slist_nth(app_list, 0); - + GSList *iter = g_slist_nth(app_list, 0); while (NULL != iter) { - temp_app = iter->data; + vc_deactivated_app_s *temp_app = iter->data; if (NULL != temp_app && NULL != temp_app->appid) { int ret = -1; @@ -402,15 +399,13 @@ static Eina_Bool __vcd_send_selected_result(void *data) SLOG(LOG_WARN, TAG_VCD, "[Server WARNING] Fail to get pid list. No result"); } else { if (0 < g_slist_length(pid_list)) { - GSList* iter = NULL; - vc_cmd_s* temp_cmd = NULL; int ret = 0; int pre_pid = -1; int pre_type = -1; - iter = g_slist_nth(pid_list, 0); + GSList *iter = g_slist_nth(pid_list, 0); while (NULL != iter) { - temp_cmd = iter->data; + vc_cmd_s *temp_cmd = iter->data; if (NULL != temp_cmd && (pre_pid != temp_cmd->pid || pre_type == VC_COMMAND_TYPE_WIDGET || temp_cmd->type == VC_COMMAND_TYPE_WIDGET)) { /* Launch deactivated several apps that is matched with result */ -- 2.7.4 From 950c1845dbade6cec1a31306247eb75d03ad60ef Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Fri, 7 Apr 2023 17:31:36 +0900 Subject: [PATCH 10/16] Invoke changed callbacks using ecore idler - Requirements: Each callbacks should not prevent main loop for a long time. - Contents: This patch fixes the logic of changed callback invocation. Through this patch, each callbacks will be invoked by ecore idler. This makes the code blocks the main loop for reasonable time. And this makes each callbacks behavior become asynchronous. Change-Id: I482e5168f3f9ff44398b5b7d067a68f37e511fd0 Signed-off-by: Suyeon Hwang --- common/vc_config_mgr.cpp | 175 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 154 insertions(+), 21 deletions(-) diff --git a/common/vc_config_mgr.cpp b/common/vc_config_mgr.cpp index e502e7e..3986088 100644 --- a/common/vc_config_mgr.cpp +++ b/common/vc_config_mgr.cpp @@ -53,6 +53,11 @@ typedef struct { int dir_wd; } vc_engine_inotify_s; +typedef struct { + char* before_lang; + char* current_lang; +} language_changed_cb_parameters_s; + static const char* vc_config_tag() { return TAG_VCCONFIG; @@ -66,6 +71,10 @@ static VoiceControlClients *g_VoiceControlClients = nullptr; static VoiceControlConfig *g_VoiceControlConfig = nullptr; +static Ecore_Idler *g_engine_changed_event_idler = NULL; +static Ecore_Idler *g_language_changed_event_idler = NULL; +static Ecore_Idler *g_enabled_changed_event_idler = NULL; + static int g_lang_ref_count; static Ecore_Fd_Handler* g_fd_handler_lang = NULL; static int g_fd_lang = -1; @@ -78,6 +87,45 @@ static int register_engine_config_updated_event(const char* path); static int unregister_engine_config_updated_event(); static int set_current_language(const char* language); +static Eina_Bool notify_engine_changed_event_by_idler(void *data) +{ + char *engine_appid = static_cast(data); + [&engine_appid]() { + if (nullptr == engine_appid) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine is not specified."); + return; + } + + if (nullptr == g_VoiceControlClients) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist"); + return; + } + + auto clients = g_VoiceControlClients->getClients(); + for (auto &clientInfo : clients) { + if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { + SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid()); + continue; + } + + clientInfo.invokeEngineChangedCallback(engine_appid); + } + }(); + + free(engine_appid); + g_engine_changed_event_idler = nullptr; + return EINA_FALSE; +} + +static inline void delete_engine_changed_event_invoker() +{ + if (nullptr != g_engine_changed_event_idler) { + void *param = ecore_idler_del(g_engine_changed_event_idler); + g_engine_changed_event_idler = nullptr; + free(static_cast(param)); + } +} + static void notify_engine_changed(const char *engine_appid) { SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke engine changed callback"); @@ -86,14 +134,63 @@ static void notify_engine_changed(const char *engine_appid) return; } - auto clients = g_VoiceControlClients->getClients(); - for (auto &clientInfo : clients) { - if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { - SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid()); - continue; + char *param = strdup(engine_appid); + if (nullptr == param) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter"); + return; + } + + delete_engine_changed_event_invoker(); + g_engine_changed_event_idler = ecore_idler_add(notify_engine_changed_event_by_idler, static_cast(param)); +} + +static inline void release_language_changed_cb_params(language_changed_cb_parameters_s *params) +{ + if (nullptr == params) { + return; + } + + free(params->before_lang); + free(params->current_lang); + delete params; +} + +static Eina_Bool notify_language_changed_event_by_idler(void *data) +{ + language_changed_cb_parameters_s *params = static_cast(data); + [¶ms]() { + if (nullptr == params) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Parameters are not specified."); + return; + } + + if (nullptr == g_VoiceControlClients) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist"); + return; + } + + auto clients = g_VoiceControlClients->getClients(); + for (auto &clientInfo : clients) { + if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { + SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid()); + continue; + } + + clientInfo.invokeLanguageChangedCallback(params->before_lang, params->current_lang); } + }(); - clientInfo.invokeEngineChangedCallback(engine_appid); + release_language_changed_cb_params(params); + g_language_changed_event_idler = nullptr; + return EINA_FALSE; +} + +static inline void delete_language_changed_event_invoker() +{ + if (nullptr != g_language_changed_event_idler) { + void *params = ecore_idler_del(g_language_changed_event_idler); + g_language_changed_event_idler = nullptr; + release_language_changed_cb_params(static_cast(params)); } } @@ -105,34 +202,70 @@ static void notify_language_changed(const char* before_lang, const char* current return; } - if (nullptr == g_VoiceControlClients) { - SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist"); + auto *params = new language_changed_cb_parameters_s(); + if (nullptr == params) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter"); return; } - auto clients = g_VoiceControlClients->getClients(); - for (auto &clientInfo : clients) { - if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { - SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid()); - continue; + params->before_lang = strdup(before_lang); + params->current_lang = strdup(current_lang); + + delete_language_changed_event_invoker(); + g_engine_changed_event_idler = ecore_idler_add(notify_language_changed_event_by_idler, static_cast(params)); +} + +static Eina_Bool notify_enabled_changed_event_by_idler(void *data) +{ + bool *enable = static_cast(data); + [&enable]() { + if (nullptr == enable) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine is not specified."); + return; + } + + if (nullptr == g_VoiceControlClients) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist"); + return; + } + + auto clients = g_VoiceControlClients->getClients(); + for (auto &clientInfo : clients) { + if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { + SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid()); + continue; + } + + clientInfo.invokeEnabledChangedCallback(*enable); } + }(); - clientInfo.invokeLanguageChangedCallback(before_lang, current_lang); + free(enable); + g_enabled_changed_event_idler = nullptr; + return EINA_FALSE; +} + +static inline void delete_enabled_changed_event_invoker() +{ + if (nullptr != g_enabled_changed_event_idler) { + void *param = ecore_idler_del(g_enabled_changed_event_idler); + g_enabled_changed_event_idler = nullptr; + free(static_cast(param)); } } static void notify_enabled_changed(bool enable) { SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke enabled callback"); - auto clients = g_VoiceControlClients->getClients(); - for (auto &clientInfo : clients) { - if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { - SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid()); - continue; - } - clientInfo.invokeEnabledChangedCallback(enable); + bool *param = new bool(enable); + if (nullptr == param) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter"); + return; } + + delete_enabled_changed_event_invoker(); + g_engine_changed_event_idler = ecore_idler_add(notify_enabled_changed_event_by_idler, static_cast(param)); } static int initialize_config_info() -- 2.7.4 From 63b20272cccf74dc3e86da7f39f2c0e4b0397800 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Fri, 7 Apr 2023 18:09:12 +0900 Subject: [PATCH 11/16] Invoke config changed callback directly - Issue: If the app changes the config using setting API, the framework did not invoke config changed callbacks. - Solution: In previous code, vc_config_mgr module could know the changes of the configuration through checking the difference between the values in the memory and actual configuration file. However, the values in the memory and configuration file are the same if the app uses the setting API. This is beecause the setting API sets the value in both the memory and file. So, this patch adds a new logic for invoking the callbacks. Through this patch, vc_config_mgr module will directly invoke the callbacks related to changed values when the app changes the configuration using setting API. Change-Id: Ic8023395889021501d8528401f9058b743699c72 Signed-off-by: Suyeon Hwang --- common/vc_config_mgr.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/common/vc_config_mgr.cpp b/common/vc_config_mgr.cpp index 3986088..9fb301e 100644 --- a/common/vc_config_mgr.cpp +++ b/common/vc_config_mgr.cpp @@ -89,6 +89,7 @@ static int set_current_language(const char* language); static Eina_Bool notify_engine_changed_event_by_idler(void *data) { + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke engine changed callback by idler"); char *engine_appid = static_cast(data); [&engine_appid]() { if (nullptr == engine_appid) { @@ -101,6 +102,7 @@ static Eina_Bool notify_engine_changed_event_by_idler(void *data) return; } + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Engine ID : %s", engine_appid); auto clients = g_VoiceControlClients->getClients(); for (auto &clientInfo : clients) { if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { @@ -157,6 +159,7 @@ static inline void release_language_changed_cb_params(language_changed_cb_parame static Eina_Bool notify_language_changed_event_by_idler(void *data) { + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke language changed callback by idler"); language_changed_cb_parameters_s *params = static_cast(data); [¶ms]() { if (nullptr == params) { @@ -169,6 +172,7 @@ static Eina_Bool notify_language_changed_event_by_idler(void *data) return; } + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Before : %s, Current : %s", params->before_lang, params->current_lang); auto clients = g_VoiceControlClients->getClients(); for (auto &clientInfo : clients) { if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { @@ -217,6 +221,7 @@ static void notify_language_changed(const char* before_lang, const char* current static Eina_Bool notify_enabled_changed_event_by_idler(void *data) { + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke enabled changed callback by idler"); bool *enable = static_cast(data); [&enable]() { if (nullptr == enable) { @@ -229,6 +234,7 @@ static Eina_Bool notify_enabled_changed_event_by_idler(void *data) return; } + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Enabled : %s", *enable ? "True" : "False"); auto clients = g_VoiceControlClients->getClients(); for (auto &clientInfo : clients) { if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) { @@ -323,6 +329,7 @@ static int check_and_set_default_engine_id(const char* engine_id) SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config"); return VC_CONFIG_ERROR_OPERATION_FAILED; } + notify_engine_changed(engineId.c_str()); g_VoiceControlConfig->setEngineId(engineId.c_str()); return VC_CONFIG_ERROR_NONE; @@ -737,6 +744,7 @@ static int set_language_by_automatic_selection() SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save default language"); return VC_CONFIG_ERROR_OPERATION_FAILED; } + notify_language_changed(before_language.c_str(), candidate_lang); g_VoiceControlConfig->setCurrentLanguage(candidate_lang); SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Default language change : before(%s) current(%s)", @@ -763,6 +771,7 @@ static int set_language_by_automatic_selection() SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config"); return VC_CONFIG_ERROR_OPERATION_FAILED; } + notify_language_changed(before_language.c_str(), tmp_language); g_VoiceControlConfig->setCurrentLanguage(tmp_language); SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Default language change : before(%s) current(%s)", @@ -1304,6 +1313,7 @@ int vc_config_mgr_set_engine(const char* engine) SLOG(LOG_ERROR, vc_config_tag(), " Fail to save config"); return VC_CONFIG_ERROR_OPERATION_FAILED; } + notify_engine_changed(engine); g_VoiceControlConfig->setEngineId(engine); /* Engine is valid*/ @@ -1406,6 +1416,7 @@ static int set_current_language(const char* language) SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save engine id"); return VC_CONFIG_ERROR_OPERATION_FAILED; } + notify_language_changed(default_language.c_str(), language); g_VoiceControlConfig->setCurrentLanguage(language); return VC_CONFIG_ERROR_NONE; @@ -1443,7 +1454,7 @@ int vc_config_mgr_set_enabled(bool value) SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set enabled"); return VC_CONFIG_ERROR_OPERATION_FAILED; } - + notify_enabled_changed(value); g_VoiceControlConfig->setEnabled(value); return VC_CONFIG_ERROR_NONE; -- 2.7.4 From aafdb2a1c449bb176b4196cd1674bac736109d8a Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Fri, 7 Apr 2023 18:16:04 +0900 Subject: [PATCH 12/16] Update version (1.75.5) Change-Id: I2c5592f9bebc39379ce7e1c6d54235b74d7b3feb Signed-off-by: Suyeon Hwang --- packaging/voice-control.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index 467a94a..515634c 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -1,6 +1,6 @@ Name: voice-control Summary: Voice control client library and daemon -Version: 1.75.4 +Version: 1.75.5 Release: 1 Group: Graphics & UI Framework/Voice Framework License: Apache-2.0 -- 2.7.4 From e03fd5910dd4e0c85da5602444629d6364fe3de5 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Fri, 7 Apr 2023 20:42:08 +0900 Subject: [PATCH 13/16] Use ecore timer for config changed callbacks Change-Id: I489807ea63d7d16529bcaf7ffa563b45c2635f56 Signed-off-by: Suyeon Hwang --- common/vc_config_mgr.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/common/vc_config_mgr.cpp b/common/vc_config_mgr.cpp index 9fb301e..6977544 100644 --- a/common/vc_config_mgr.cpp +++ b/common/vc_config_mgr.cpp @@ -71,9 +71,9 @@ static VoiceControlClients *g_VoiceControlClients = nullptr; static VoiceControlConfig *g_VoiceControlConfig = nullptr; -static Ecore_Idler *g_engine_changed_event_idler = NULL; -static Ecore_Idler *g_language_changed_event_idler = NULL; -static Ecore_Idler *g_enabled_changed_event_idler = NULL; +static Ecore_Timer *g_engine_changed_event_invoker = NULL; +static Ecore_Timer *g_language_changed_event_invoker = NULL; +static Ecore_Timer *g_enabled_changed_event_invoker = NULL; static int g_lang_ref_count; static Ecore_Fd_Handler* g_fd_handler_lang = NULL; @@ -87,9 +87,9 @@ static int register_engine_config_updated_event(const char* path); static int unregister_engine_config_updated_event(); static int set_current_language(const char* language); -static Eina_Bool notify_engine_changed_event_by_idler(void *data) +static Eina_Bool notify_engine_changed_event_by_invoker(void *data) { - SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke engine changed callback by idler"); + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke engine changed callback asynchronously"); char *engine_appid = static_cast(data); [&engine_appid]() { if (nullptr == engine_appid) { @@ -115,15 +115,15 @@ static Eina_Bool notify_engine_changed_event_by_idler(void *data) }(); free(engine_appid); - g_engine_changed_event_idler = nullptr; + g_engine_changed_event_invoker = nullptr; return EINA_FALSE; } static inline void delete_engine_changed_event_invoker() { - if (nullptr != g_engine_changed_event_idler) { - void *param = ecore_idler_del(g_engine_changed_event_idler); - g_engine_changed_event_idler = nullptr; + if (nullptr != g_engine_changed_event_invoker) { + void *param = ecore_timer_del(g_engine_changed_event_invoker); + g_engine_changed_event_invoker = nullptr; free(static_cast(param)); } } @@ -143,7 +143,7 @@ static void notify_engine_changed(const char *engine_appid) } delete_engine_changed_event_invoker(); - g_engine_changed_event_idler = ecore_idler_add(notify_engine_changed_event_by_idler, static_cast(param)); + g_engine_changed_event_invoker = ecore_timer_add(0.0, notify_engine_changed_event_by_invoker, static_cast(param)); } static inline void release_language_changed_cb_params(language_changed_cb_parameters_s *params) @@ -157,9 +157,9 @@ static inline void release_language_changed_cb_params(language_changed_cb_parame delete params; } -static Eina_Bool notify_language_changed_event_by_idler(void *data) +static Eina_Bool notify_language_changed_event_by_invoker(void *data) { - SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke language changed callback by idler"); + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke language changed callback asynchronously"); language_changed_cb_parameters_s *params = static_cast(data); [¶ms]() { if (nullptr == params) { @@ -185,15 +185,15 @@ static Eina_Bool notify_language_changed_event_by_idler(void *data) }(); release_language_changed_cb_params(params); - g_language_changed_event_idler = nullptr; + g_language_changed_event_invoker = nullptr; return EINA_FALSE; } static inline void delete_language_changed_event_invoker() { - if (nullptr != g_language_changed_event_idler) { - void *params = ecore_idler_del(g_language_changed_event_idler); - g_language_changed_event_idler = nullptr; + if (nullptr != g_language_changed_event_invoker) { + void *params = ecore_timer_del(g_language_changed_event_invoker); + g_language_changed_event_invoker = nullptr; release_language_changed_cb_params(static_cast(params)); } } @@ -216,12 +216,12 @@ static void notify_language_changed(const char* before_lang, const char* current params->current_lang = strdup(current_lang); delete_language_changed_event_invoker(); - g_engine_changed_event_idler = ecore_idler_add(notify_language_changed_event_by_idler, static_cast(params)); + g_language_changed_event_invoker = ecore_timer_add(0.0, notify_language_changed_event_by_invoker, static_cast(params)); } -static Eina_Bool notify_enabled_changed_event_by_idler(void *data) +static Eina_Bool notify_enabled_changed_event_by_invoker(void *data) { - SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke enabled changed callback by idler"); + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke enabled changed callback asynchronously"); bool *enable = static_cast(data); [&enable]() { if (nullptr == enable) { @@ -247,15 +247,15 @@ static Eina_Bool notify_enabled_changed_event_by_idler(void *data) }(); free(enable); - g_enabled_changed_event_idler = nullptr; + g_enabled_changed_event_invoker = nullptr; return EINA_FALSE; } static inline void delete_enabled_changed_event_invoker() { - if (nullptr != g_enabled_changed_event_idler) { - void *param = ecore_idler_del(g_enabled_changed_event_idler); - g_enabled_changed_event_idler = nullptr; + if (nullptr != g_enabled_changed_event_invoker) { + void *param = ecore_timer_del(g_enabled_changed_event_invoker); + g_enabled_changed_event_invoker = nullptr; free(static_cast(param)); } } @@ -271,7 +271,7 @@ static void notify_enabled_changed(bool enable) } delete_enabled_changed_event_invoker(); - g_engine_changed_event_idler = ecore_idler_add(notify_enabled_changed_event_by_idler, static_cast(param)); + g_enabled_changed_event_invoker = ecore_timer_add(0.0, notify_enabled_changed_event_by_invoker, static_cast(param)); } static int initialize_config_info() -- 2.7.4 From b9a763ff4246f7db5bf05d35b3de7a85dfe03769 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Fri, 7 Apr 2023 21:20:36 +0900 Subject: [PATCH 14/16] Update version (1.75.6) Change-Id: I6c8ceefed4d5b35c5c8178aea80f77cf3bf3413a Signed-off-by: Suyeon Hwang --- packaging/voice-control.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/voice-control.spec b/packaging/voice-control.spec index 515634c..0ddace7 100644 --- a/packaging/voice-control.spec +++ b/packaging/voice-control.spec @@ -1,6 +1,6 @@ Name: voice-control Summary: Voice control client library and daemon -Version: 1.75.5 +Version: 1.75.6 Release: 1 Group: Graphics & UI Framework/Voice Framework License: Apache-2.0 -- 2.7.4 From 65d4f917f9dc3bf7339a85a5610eebbe3d4144a1 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Mon, 10 Apr 2023 18:06:35 +0900 Subject: [PATCH 15/16] Add timer for callbacks in main loop - Issue: When the app calls setting API in sub-thread, the changed callback can not be invoked properly. - Solution: Most ecore API function properly works in main loop, and ecore_timer_add() is also a functions of this kind. Therefore, if the app calls setting API function in sub-thread, the changed event callbacks can not be invoked. To solve this issue, this patch changes the ecore timer registration logic. Through this patch, every timer will be added in main loop by ecore_main_loop_thread_safe_call_sync(). Change-Id: I8ce976cf2b86b1c2a309ea887f17f1641b9e3f01 Signed-off-by: Suyeon Hwang --- common/vc_config_mgr.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/common/vc_config_mgr.cpp b/common/vc_config_mgr.cpp index 6977544..d45d930 100644 --- a/common/vc_config_mgr.cpp +++ b/common/vc_config_mgr.cpp @@ -142,8 +142,12 @@ static void notify_engine_changed(const char *engine_appid) return; } - delete_engine_changed_event_invoker(); - g_engine_changed_event_invoker = ecore_timer_add(0.0, notify_engine_changed_event_by_invoker, static_cast(param)); + ecore_main_loop_thread_safe_call_sync([](void *data) -> void * { + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Register timer for engine changed event"); + delete_engine_changed_event_invoker(); + g_engine_changed_event_invoker = ecore_timer_add(0.0, notify_engine_changed_event_by_invoker, data); + return nullptr; + }, static_cast(param)); } static inline void release_language_changed_cb_params(language_changed_cb_parameters_s *params) @@ -215,8 +219,12 @@ static void notify_language_changed(const char* before_lang, const char* current params->before_lang = strdup(before_lang); params->current_lang = strdup(current_lang); - delete_language_changed_event_invoker(); - g_language_changed_event_invoker = ecore_timer_add(0.0, notify_language_changed_event_by_invoker, static_cast(params)); + ecore_main_loop_thread_safe_call_sync([](void *data) -> void * { + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Register timer for language changed event"); + delete_language_changed_event_invoker(); + g_language_changed_event_invoker = ecore_timer_add(0.0, notify_language_changed_event_by_invoker, data); + return nullptr; + }, static_cast(params)); } static Eina_Bool notify_enabled_changed_event_by_invoker(void *data) @@ -270,8 +278,12 @@ static void notify_enabled_changed(bool enable) return; } - delete_enabled_changed_event_invoker(); - g_enabled_changed_event_invoker = ecore_timer_add(0.0, notify_enabled_changed_event_by_invoker, static_cast(param)); + ecore_main_loop_thread_safe_call_sync([](void *data) -> void * { + SLOG(LOG_INFO, vc_config_tag(), "[INFO] Register timer for enabled changed event"); + delete_enabled_changed_event_invoker(); + g_enabled_changed_event_invoker = ecore_timer_add(0.0, notify_enabled_changed_event_by_invoker, data); + return nullptr; + }, static_cast(param)); } static int initialize_config_info() -- 2.7.4 From 57554881ad705d962840581695a7e6152907f5ca Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Tue, 11 Apr 2023 13:40:32 +0900 Subject: [PATCH 16/16] Register fd handler when the client only sets the lang_cb - Issue: Language changes callback is not invoked except by the setting client. - Solution: Previous code does not register inotify fd handler when the clients only set langauge changed callback. The callback needs fd handler registeration because the callback is called by fd handler. So this patch adds code to register the fd handler. Through this patch, the language changd callback will be invoked even if the client is not the setting client. Change-Id: I503a5097f7727721292974bd1dc2919401e17593 Signed-off-by: Suyeon Hwang --- common/vc_config_mgr.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/vc_config_mgr.cpp b/common/vc_config_mgr.cpp index d45d930..1b98486 100644 --- a/common/vc_config_mgr.cpp +++ b/common/vc_config_mgr.cpp @@ -1094,6 +1094,13 @@ int vc_config_mgr_set_lang_cb(unsigned int uid, vc_config_lang_changed_cb lang_c } g_VoiceControlClients->setLanguageChangedCallback(uid, lang_cb); + + if (VC_CONFIG_ERROR_NONE != register_language_config_changed_event()) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to register config event"); + ecore_thread_main_loop_end(); + return VC_CONFIG_ERROR_OPERATION_FAILED; + } + ecore_thread_main_loop_end(); return VC_CONFIG_ERROR_NONE; } @@ -1108,6 +1115,9 @@ int vc_config_mgr_unset_lang_cb(unsigned int uid) } g_VoiceControlClients->setLanguageChangedCallback(uid, nullptr); + + unregister_language_config_event(); + ecore_thread_main_loop_end(); return VC_CONFIG_ERROR_NONE; } -- 2.7.4