From: Suyeon Hwang Date: Tue, 10 Jan 2023 05:23:20 +0000 (+0900) Subject: Check and try to recreate the handle if the handle is invalid X-Git-Tag: accepted/tizen/7.0/unified/20230116.165318~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=aaa91353b671a8e7fdb7e014214831b383040e23;p=platform%2Fcore%2Fuifw%2Ftts.git Check and try to recreate the handle if the handle is invalid - Issue: Sometimes, the handle creation for audio framework is failed, but the stt framework try to use this invalid handle. - Solution: The AudioStream class did not set nullptr to audio handles. Because of this behavior, if the handle was not created from the audio framework, the AudioStream class tried to use garbage pointer as audio handle. This caused some crashes. To solve this issue, this patch makes the AudioStream class initialize the audio handle as nullptr. And also, this patch adds new code for re-creating audio handles of AudioStream and BackgroundVolume class. This new code is going to be invoked when some audio handles are not valid. Change-Id: I7c98473bf9ced056e4a6dfd579455e94db0b9993 Signed-off-by: Suyeon Hwang --- diff --git a/server/AudioStream.cpp b/server/AudioStream.cpp index f91b0c47..5dd41c17 100644 --- a/server/AudioStream.cpp +++ b/server/AudioStream.cpp @@ -23,37 +23,17 @@ using namespace std; static const char* FOCUS_SERVER_READY = "/tmp/.focus_server_ready"; -AudioStream::AudioStream() +AudioStream::AudioStream(): + __audioHandle(nullptr), + __audioType(TTSE_AUDIO_TYPE_RAW_S16), + __audioRate(16000), + __prepared(false), + __streamInfo(nullptr), + __focusAquired(false), + __state(AUDIO_STATE_NONE) { - __prepared = false; - __focusAquired = false; - createSoundStreamInfo(); - createAudioHandle(TTSE_AUDIO_TYPE_RAW_S16, 16000); -} - -void AudioStream::createSoundStreamInfo() -{ - int cnt = 0; - while (1) { - if (0 == access(FOCUS_SERVER_READY, F_OK)) { - SLOG(LOG_ERROR, tts_tag(), "[AudioStream] focus server is available"); - break; - } else { - if (0 == cnt++ % 10) - SLOG(LOG_ERROR, tts_tag(), "[AudioStream] focus server is not available"); - usleep(50000); - } - } - - int ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_INFORMATION, __focusStateChangedCallback, this, &__streamInfo); - if (SOUND_MANAGER_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create stream info"); - return; - } - - __focusAquired = false; - SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Create stream info"); + createAudioHandle(__audioType, __audioRate); } AudioStream::~AudioStream() @@ -99,6 +79,22 @@ int AudioStream::setAudioFormat(ttse_audio_type_e type, int rate) int AudioStream::acquireSoundFocus() { + if (isAudioHandleValid() == false) { + int ret = createAudioHandle(__audioType, __audioRate); + if (TTSD_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create the audio handle. ret(%s)", get_error_message(ret)); + return TTSD_ERROR_OPERATION_FAILED; + } + } + + if (isStreamInfoValid() == false) { + int ret = createSoundStreamInfo(); + if (TTSD_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create the stream info. ret(%s)", get_error_message(ret)); + return TTSD_ERROR_OPERATION_FAILED; + } + } + int ret = sound_manager_acquire_focus(__streamInfo, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, nullptr); if (SOUND_MANAGER_ERROR_NONE != ret) { SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to acquire focus. ret(%s)", get_error_message(ret)); @@ -118,7 +114,12 @@ int AudioStream::acquireSoundFocus() int AudioStream::releaseSoundFocus() { - sound_stream_focus_state_e focusState = SOUND_STREAM_FOCUS_STATE_ACQUIRED; + if (isStreamInfoValid() == false) { + SLOG(LOG_INFO, tts_tag(), "[AudioStream] Handle is not created. No focus acquired"); + return TTSD_ERROR_NONE; + } + + sound_stream_focus_state_e focusState = SOUND_STREAM_FOCUS_STATE_RELEASED; int ret = sound_manager_get_focus_state(__streamInfo, &focusState, nullptr); if (SOUND_MANAGER_ERROR_NONE != ret) { SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to get focus state: %d", ret); @@ -146,6 +147,14 @@ int AudioStream::prepareAudioOut() return TTSD_ERROR_NONE; } + if (isAudioHandleValid() == false) { + int ret = createAudioHandle(__audioType, __audioRate); + if (TTSD_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create the audio handle. ret(%s)", get_error_message(ret)); + return TTSD_ERROR_OPERATION_FAILED; + } + } + int ret = audio_out_prepare(__audioHandle); if (AUDIO_IO_ERROR_NONE != ret) { SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to prepare audio : %d", ret); @@ -164,6 +173,11 @@ int AudioStream::playAudioData(char* buffer, unsigned int length) return TTSD_ERROR_OPERATION_FAILED; } + if (isAudioHandleValid() == false) { + SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Handle is not created"); + return TTSD_ERROR_OPERATION_FAILED; + } + int ret = audio_out_write(__audioHandle, static_cast(buffer), length); if (0 > ret) { SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to audio write - %d", ret); @@ -180,6 +194,11 @@ int AudioStream::unprepareAudioOut() return TTSD_ERROR_NONE; } + if (isAudioHandleValid() == false) { + SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Handle is not created. No prepared handle."); + return TTSD_ERROR_NONE; + } + int ret = audio_out_unprepare(__audioHandle); if (AUDIO_IO_ERROR_NONE != ret) { SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to prepare audio : %d", ret); @@ -191,6 +210,24 @@ int AudioStream::unprepareAudioOut() return TTSD_ERROR_NONE; } +bool AudioStream::isAudioHandleValid() +{ + if (__audioHandle == nullptr) { + return false; + } + + return true; +} + +bool AudioStream::isStreamInfoValid() +{ + if (__streamInfo == nullptr) { + return false; + } + + return true; +} + void AudioStream::waitForPlay() { __state = AUDIO_STATE_WAIT_FOR_PLAYING; @@ -241,6 +278,32 @@ void AudioStream::destroyAudioHandle() __state = AUDIO_STATE_NONE; } +int AudioStream::createSoundStreamInfo() +{ + int cnt = 0; + while (1) { + if (0 == access(FOCUS_SERVER_READY, F_OK)) { + SLOG(LOG_ERROR, tts_tag(), "[AudioStream] focus server is available"); + break; + } else { + if (0 == cnt++ % 10) + SLOG(LOG_ERROR, tts_tag(), "[AudioStream] focus server is not available"); + usleep(50000); + } + } + + int ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_INFORMATION, __focusStateChangedCallback, this, &__streamInfo); + if (SOUND_MANAGER_ERROR_NONE != ret || __streamInfo == nullptr) { + SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create stream info(%d/%s)", ret, get_error_message(ret)); + __streamInfo = nullptr; + return TTSD_ERROR_OPERATION_FAILED; + } + + __focusAquired = false; + SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Create stream info"); + return TTSD_ERROR_NONE; +} + void AudioStream::__focusStateChangedCallback(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason_for_change, int sound_behavior, const char *extra_info, void *user_data) diff --git a/server/AudioStream.h b/server/AudioStream.h index 332eae95..8ae0a079 100644 --- a/server/AudioStream.h +++ b/server/AudioStream.h @@ -48,10 +48,13 @@ private: sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason_for_change, int sound_behavior, const char *extra_info, void *user_data); + bool isAudioHandleValid(); + bool isStreamInfoValid(); + int createAudioHandle(ttse_audio_type_e type, int rate); void destroyAudioHandle(); - void createSoundStreamInfo(); + int createSoundStreamInfo(); void destroySoundStreamInfo(); private: diff --git a/server/BackgroundVolume.cpp b/server/BackgroundVolume.cpp index d5f81e13..fd7f6a9b 100644 --- a/server/BackgroundVolume.cpp +++ b/server/BackgroundVolume.cpp @@ -44,23 +44,20 @@ static void __sound_stream_ducking_state_changed_cb(sound_stream_ducking_h strea } BackgroundVolume::BackgroundVolume(long long int duckingDuration): - __duckingDuration(duckingDuration), __mediaStream(nullptr), __notificationStream(nullptr), __alarmStream(nullptr), - __postponedRecoverTimer(nullptr), __postponedModifyTimer(nullptr) + __duckingDuration(duckingDuration), + __mediaStream(nullptr), + __notificationStream(nullptr), + __alarmStream(nullptr), + __volumeRatio(0.0), + __isVolumeDucked(false), + __changeVolumeTime(chrono::steady_clock::now()), + __postponedRecoverTimer(nullptr), + __postponedModifyTimer(nullptr) { - int ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_MEDIA, __sound_stream_ducking_state_changed_cb, nullptr, &__mediaStream); - if (SOUND_MANAGER_ERROR_NONE != ret) - SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for type media, ret(%d)", ret); - - ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_NOTIFICATION, __sound_stream_ducking_state_changed_cb, nullptr, &__notificationStream); - if (SOUND_MANAGER_ERROR_NONE != ret) - SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for notification type, ret(%d)", ret); - - ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_ALARM, __sound_stream_ducking_state_changed_cb, nullptr, &__alarmStream); - if (SOUND_MANAGER_ERROR_NONE != ret) - SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for alarm type, ret(%d)", ret); - - __isVolumeDucked = false; - __volumeRatio = 0.0; + int ret = createHandles(); + if (TTSD_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[BackgroundVolume] Fail to create handles."); + } } BackgroundVolume::~BackgroundVolume() @@ -205,6 +202,15 @@ void BackgroundVolume::changeVolumeOnMainThread(void* data) void BackgroundVolume::activateDuckingAll(unsigned int duration, double ratio) { + if (false == isDuckingHandleValid()) { + SLOG(LOG_WARN, tts_tag(), "[BackgroundVolume] There are some invalid handles. Try to recreate the hnadles"); + int ret = createHandles(); + if (TTSD_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[BackgroundVolume] Fail to create handles. Skip ducking activation."); + return; + } + } + activateDucking(SOUND_STREAM_TYPE_MEDIA, duration, ratio); activateDucking(SOUND_STREAM_TYPE_NOTIFICATION, duration, ratio); activateDucking(SOUND_STREAM_TYPE_ALARM, duration, ratio); @@ -278,6 +284,11 @@ long long int BackgroundVolume::getDurationAfterDucking() void BackgroundVolume::deactivateDuckingAll() { + if (false == isDuckingHandleValid()) { + SLOG(LOG_WARN, tts_tag(), "[BackgroundVolume] There are some invalid handles. Skip ducking deactivation."); + return; + } + deactivateDucking(SOUND_STREAM_TYPE_MEDIA); deactivateDucking(SOUND_STREAM_TYPE_NOTIFICATION); deactivateDucking(SOUND_STREAM_TYPE_ALARM); @@ -315,6 +326,49 @@ void BackgroundVolume::deactivateDucking(sound_stream_type_e type) } } +int BackgroundVolume::createHandles() +{ + SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Create ducking handles"); + + if (nullptr == __mediaStream) { + int ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_MEDIA, __sound_stream_ducking_state_changed_cb, nullptr, &__mediaStream); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for type media, ret(%d/%s)", ret, get_error_message(ret)); + __mediaStream = nullptr; + return TTSD_ERROR_OPERATION_FAILED; + } + } + + if (nullptr == __notificationStream) { + int ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_NOTIFICATION, __sound_stream_ducking_state_changed_cb, nullptr, &__notificationStream); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for notification type, ret(%d/%s)", ret, get_error_message(ret)); + __notificationStream = nullptr; + return TTSD_ERROR_OPERATION_FAILED; + } + } + + if (nullptr == __alarmStream) { + int ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_ALARM, __sound_stream_ducking_state_changed_cb, nullptr, &__alarmStream); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for alarm type, ret(%d/%s)", ret, get_error_message(ret)); + __alarmStream = nullptr; + return TTSD_ERROR_OPERATION_FAILED; + } + } + + return TTSD_ERROR_NONE; +} + +bool BackgroundVolume::isDuckingHandleValid() +{ + if (__mediaStream == nullptr || __notificationStream == nullptr || __alarmStream == nullptr) { + return false; + } + + return true; +} + sound_stream_ducking_h BackgroundVolume::getStreamDuckingHandle(sound_stream_type_e type) { switch (type) diff --git a/server/BackgroundVolume.h b/server/BackgroundVolume.h index bc61b1fc..1a3ff7a9 100644 --- a/server/BackgroundVolume.h +++ b/server/BackgroundVolume.h @@ -41,6 +41,8 @@ private: static Eina_Bool postponedRecoverTimerCb(void* data); static Eina_Bool postponedModifyTimerCb(void* data); + int createHandles(); + bool isDuckingHandleValid(); long long int getDurationAfterDucking(); sound_stream_ducking_h getStreamDuckingHandle(sound_stream_type_e type);