Check and try to recreate the handle if the handle is invalid 78/286578/3
authorSuyeon Hwang <stom.hwang@samsung.com>
Tue, 10 Jan 2023 05:23:20 +0000 (14:23 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Tue, 10 Jan 2023 06:54:23 +0000 (15:54 +0900)
- 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 <stom.hwang@samsung.com>
server/AudioStream.cpp
server/AudioStream.h
server/BackgroundVolume.cpp
server/BackgroundVolume.h

index f91b0c47ae9d74cee4f2060f9f16211148f3b9f2..5dd41c17dcc7f76d573ae1f60a58e1d530e44385 100644 (file)
@@ -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<void*>(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)
index 332eae953152ecfb4ee7fc390fdb5f8d069d7730..8ae0a079751febd4ac23090eb20da9c783f69357 100644 (file)
@@ -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:
index d5f81e13bcf27862f69cf18170c198b22e01a13f..fd7f6a9b6dce0506932f0222a088ba5151dd8b54 100644 (file)
@@ -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)
index bc61b1fcc2624102b2630f89612d6d86ab09296e..1a3ff7a9a376e13d0d330a11dcccfe5a727f1f64 100644 (file)
@@ -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);