Avoid infinite blocking on internalWait() by replacing cond_wait with cond_timedwait
[platform/core/api/audio-io.git] / src / cpp / CAudioIO.cpp
index 1f875b2..bda8400 100644 (file)
  */
 
 
-#include <mm.h>
 #include <pthread.h>
 #include <assert.h>
 #include "CAudioIODef.h"
-
-#define AUDIO_IO_DEBUG
+#include <sound_manager_internal.h>
+#include <sys/time.h>
+#include <string.h>
 
 using namespace std;
 using namespace tizen_media_audio;
@@ -29,34 +29,33 @@ using namespace tizen_media_audio;
 /**
  * class CAudioIO
  */
+//LCOV_EXCL_START
 CAudioIO::CAudioIO() :
-    mpAudioSessionHandler(NULL),
-    mpPulseAudioClient(NULL),
+    mpPulseAudioClient(nullptr),
     __mMutex(PTHREAD_MUTEX_INITIALIZER),
+    __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
     __mCond(PTHREAD_COND_INITIALIZER),
-    __mIsInit(false),
-    __mForceIgnore(false) {
+    __mIsInit(false) {
+    mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
     mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mByPolicy = false;
 }
+//LCOV_EXCL_STOP
 
 CAudioIO::CAudioIO(CAudioInfo& audioInfo) :
-    mpAudioSessionHandler(NULL),
-    mpPulseAudioClient(NULL),
+    mpPulseAudioClient(nullptr),
     __mMutex(PTHREAD_MUTEX_INITIALIZER),
+    __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
     __mCond(PTHREAD_COND_INITIALIZER),
-    __mIsInit(false),
-    __mForceIgnore(false) {
+    __mIsInit(false) {
     mAudioInfo = audioInfo;
+    mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
     mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mByPolicy = false;
 }
 
-CAudioIO::~CAudioIO() {
-}
-
 void CAudioIO::setInit(bool flag) {
     __mIsInit = flag;
 }
@@ -66,410 +65,318 @@ bool CAudioIO::isInit() {
 }
 
 bool CAudioIO::IsReady() {
-    return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING || mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED)? true : false);
+    return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING ||
+             mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED));
 }
 
-void CAudioIO::internalLock() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+void CAudioIO::internalLock() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
+
+    if (pthread_mutex_lock(&__mMutex) != 0)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()"); //LCOV_EXCL_LINE
 
-    if (pthread_mutex_lock(&__mMutex) != 0) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
-    }
 #ifdef _AUDIO_IO_DEBUG_TIMING_
-    AUDIO_IO_LOGD(COLOR_RED "LOCK" COLOR_END);
+    AUDIO_IO_LOGD(COLOR_RED "%p LOCKED" COLOR_END, &__mMutex);
 #endif
 }
 
-void CAudioIO::internalUnlock() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+void CAudioIO::internalUnlock() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
+
+    if (pthread_mutex_unlock(&__mMutex) != 0)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()"); //LCOV_EXCL_LINE
 
-    if (pthread_mutex_unlock(&__mMutex) != 0) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
-    }
 #ifdef _AUDIO_IO_DEBUG_TIMING_
-    AUDIO_IO_LOGD(COLOR_GREEN "UNLOCK" COLOR_END);
+    AUDIO_IO_LOGD(COLOR_GREEN "%p UNLOCKED" COLOR_END, &__mMutex);
 #endif
 }
 
-void CAudioIO::internalWait() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+void CAudioIO::internalWait() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 
 #ifdef _AUDIO_IO_DEBUG_TIMING_
     AUDIO_IO_LOGD(COLOR_RED "WAIT" COLOR_END);
 #endif
+    pthread_mutex_lock(&__mCondMutex);
 
-    pthread_cond_wait(&__mCond, &__mMutex);
-}
+    struct timeval now = { 0, };
+    struct timeval to_wait = { 0, };
+    struct timeval until = { 0, };
+    struct timespec until_ts = { 0, };
+
+    constexpr int COND_TIMEOUT_MS = 200;
 
-void CAudioIO::internalSignal() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    gettimeofday(&now, nullptr);
+    to_wait.tv_sec = COND_TIMEOUT_MS / 1000UL;
+    to_wait.tv_usec = (COND_TIMEOUT_MS % 1000UL) * 1000UL;
+    timeradd(&now, &to_wait, &until);
+    until_ts.tv_sec = until.tv_sec;
+    until_ts.tv_nsec = until.tv_usec * 1000UL;
+
+    if (pthread_cond_timedwait(&__mCond, &__mCondMutex, &until_ts) != 0) {
+        char str_error[256];
+        AUDIO_IO_LOGE("pthread_cond_timedwait error=%s", strerror_r(errno, str_error, sizeof(str_error)));
     }
 
+    pthread_mutex_unlock(&__mCondMutex);
+}
+
+void CAudioIO::internalSignal() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
+
 #ifdef _AUDIO_IO_DEBUG_TIMING_
     AUDIO_IO_LOGD(COLOR_GREEN "SIGNAL" COLOR_END);
 #endif
 
+    pthread_mutex_lock(&__mCondMutex);
     pthread_cond_signal(&__mCond);
+    pthread_mutex_unlock(&__mCondMutex);
 }
 
-bool CAudioIO::isForceIgnore() {
-    return __mForceIgnore;
-}
-
-void CAudioIO::initialize() throw (CAudioError) {
-    if (__mIsInit == true) {
+void CAudioIO::initialize() {
+    if (__mIsInit)
         return;
-    }
 
     AUDIO_IO_LOGD("initialize");
 
     int ret = pthread_mutex_init(&__mMutex, NULL);
-    if (ret != 0) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_init()");
-    }
+    if (ret != 0)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_init()"); //LCOV_EXCL_LINE
 
     ret = pthread_cond_init(&__mCond, NULL);
-    if (ret != 0) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_init()");
-    }
+    if (ret != 0)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_init()"); //LCOV_EXCL_LINE
 
     __mIsInit = true;
 }
 
 void CAudioIO::finalize() {
-    if (__mIsInit == false) {
+    if (!__mIsInit)
         return;
-    }
 
     AUDIO_IO_LOGD("finalize");
 
+    bool error_occured = false;
     int ret = pthread_mutex_destroy(&__mMutex);
     if (ret != 0) {
-        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_destroy() ret:%d", ret);
+//LCOV_EXCL_START
+        AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mMutex, ret);
+        error_occured = true;
+//LCOV_EXCL_STOP
+    }
+
+    ret = pthread_mutex_destroy(&__mCondMutex);
+    if (ret != 0) {
+//LCOV_EXCL_START
+        AUDIO_IO_LOGE("Failed cond pthread_mutex_destroy(%p) errno:%d", &__mCondMutex, ret);
+        error_occured = true;
+//LCOV_EXCL_STOP
     }
 
     ret = pthread_cond_destroy(&__mCond);
     if (ret != 0) {
-        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_destroy() ret:%d", ret);
+//LCOV_EXCL_START
+        AUDIO_IO_LOGE("Failed pthread_cond_destroy(%p) errno:%d", &__mCond, ret);
+        error_occured = true;
+//LCOV_EXCL_STOP
     }
 
+    if (error_occured)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Finalize Failed"); //LCOV_EXCL_LINE
+
     __mIsInit = false;
 }
 
 void CAudioIO::onStream(CPulseAudioClient* pClient, size_t length) {
-    assert(__mIsInit == true);
-    assert(pClient != NULL);
+    assert(__mIsInit);
+    assert(pClient);
     assert(length > 0);
 
 #ifdef _AUDIO_IO_DEBUG_TIMING_
     AUDIO_IO_LOGD("mStreamCallback.onStream(%p), pClient(%p), length(%zu)", mStreamCallback.onStream, pClient, length);
 #endif
 
-    if (mStreamCallback.onStream != NULL) {
+    if (mStreamCallback.onStream)
         mStreamCallback.onStream(length, mStreamCallback.mUserData);
-    }
 }
 
 void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) {
-    assert(__mIsInit == true);
+    assert(__mIsInit);
     assert(state >= CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE && state < CAudioInfo::EAudioIOState::AUDIO_IO_STATE_MAX);
 
     mStatePrev = mState;
-    mState     = state;
-    mByPolicy  = byPolicy;
+    mState = state;
+    mByPolicy = byPolicy;
+
+    if (mState == mStatePrev)
+        return;
+
+    static const char* state_string[] = { "NONE", "IDLE", "RUNNING", "PAUSED" };
 
-    AUDIO_IO_LOGD("current(%d), previous(%d), by_policy(%d)", mState, mStatePrev, mByPolicy);
+    AUDIO_IO_LOGD("previous(%s,%d) ===> current(%s,%d), by_policy(%d)",
+                  state_string[static_cast<int>(mStatePrev)],
+                  static_cast<int>(mStatePrev),
+                  state_string[static_cast<int>(mState)],
+                  static_cast<int>(mState),
+                  mByPolicy);
 
-    if (mStateChangedCallback.onStateChanged != NULL) {
+    if (mStateChangedCallback.onStateChanged)
         mStateChangedCallback.onStateChanged(mState, mStatePrev, mByPolicy, mStateChangedCallback.mUserData);
-    }
 }
 
 void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state) {
     onStateChanged(state, false);
 }
 
-void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info) {
-    assert(pHandler);
-
-    int session_option = pHandler->getOptions();
-
-    if (id == -1) {
-        ///////////////////////////////////////
-        // Triggered by 'focus watch callback'
-        ///////////////////////////////////////
-
-        if (session_option & (MM_SESSION_OPTION_PAUSE_OTHERS | MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
-            AUDIO_IO_LOGD("Session option is pausing others or uninterruptible, skip...");
-            return;
-        }
-
-        if (state == FOCUS_IS_RELEASED) {
-            // Focus handle(id) of the other application was released, do resume if possible
-            internalLock();
-
-            mpPulseAudioClient->cork(false);
-            onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING);
-
-            internalUnlock();
-
-            // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
-            state = FOCUS_IS_ACQUIRED;
-        } else if (state == FOCUS_IS_ACQUIRED) {
-            // Focus handle(id) of the other application was acquired, do pause if possible
-            internalLock();
-
-            if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK) {
-                if (mpPulseAudioClient->drain() == false) {
-                    AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()");
-                }
-            }
-
-            mpPulseAudioClient->cork(true);
-            onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED);
-
-            internalUnlock();
-
-            // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
-            state = FOCUS_IS_RELEASED;
-        }
-    } else {
-        ///////////////////////////////////////
-        // Triggered by 'focus callback'
-        ///////////////////////////////////////
-
-        if (pHandler->getId() != id) {
-            AUDIO_IO_LOGW("Id is different, why? [mId : %d]", pHandler->getId());
-        }
-
-        if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
-            AUDIO_IO_LOGD("Session option is uninterruptible, skip...");
-            return;
-        }
-
-        if (state == FOCUS_IS_RELEASED) {
-            // Focus handle(id) was released, do pause here
-            internalLock();
-
-            if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::EStreamDirection::STREAM_DIRECTION_PLAYBACK) {
-                if (mpPulseAudioClient->drain() == false) {
-                    AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()");
-                }
-            }
-
-            mpPulseAudioClient->cork(true);
-            onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED);
-
-            internalUnlock();
-        } else if (state == FOCUS_IS_ACQUIRED) {
-            // Focus handle(id) was acquired again,
-            // check reason_for_change ("call-voice","call-video","voip","alarm","notification", ...)
-            // do resume here and call interrupt completed callback to application.
-            internalLock();
-
-            mpPulseAudioClient->cork(false);
-            onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING);
-
-            internalUnlock();
-        }
-    }
-
-    if (mInterruptCallback.onInterrupt != NULL) {
-        IAudioSessionEventListener::EInterruptCode e = IAudioSessionEventListener::EInterruptCode::INTERRUPT_COMPLETED;
-        e = IAudioSessionEventListener::convertInterruptedCode(state, reason_for_change);
-        mInterruptCallback.onInterrupt(e, mInterruptCallback.mUserData);
-    }
+CAudioInfo::EAudioIOState CAudioIO::getState() noexcept {
+    return mState;
 }
 
-void CAudioIO::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) {
-    assert(pHandler);
-
-    if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
-        if (value == 1 && pHandler->getSubscribeId() >= 0) {
-            // Unregister focus watch callback & disable session handler
-            pHandler->disableSessionHandler();
-            AUDIO_IO_LOGD("Session handler disabled by signal");
-        } else if (value == 0) {
-            // Currently do nothing...
-        }
-    }
-}
-
-void CAudioIO::prepare() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
-
-    try {
-        AUDIO_IO_LOGD("prepare");
-        /* Do nothing */
-    } catch (CAudioError e) {
-        throw e;
-    }
+void CAudioIO::prepare() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 }
 
-void CAudioIO::unprepare() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
-
-    try {
-        AUDIO_IO_LOGD("unprepare");
-        /* Do nothing */
-    } catch (CAudioError e) {
-        throw e;
-    }
+void CAudioIO::unprepare() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 }
 
-void CAudioIO::pause() throw (CAudioError) {
-    if (__mIsInit == false || IsReady() == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
-    }
+void CAudioIO::pause() {
+    if (!__mIsInit || !IsReady())
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); //LCOV_EXCL_LINE
 
     try {
         internalLock();
         AUDIO_IO_LOGD("pause");
         mpPulseAudioClient->cork(true);
         internalUnlock();
-    } catch (CAudioError e) {
+    } catch (const CAudioError& e) {
         internalUnlock();
-        throw e;
+        throw;
     }
 }
 
-void CAudioIO::resume() throw (CAudioError) {
-    if (__mIsInit == false || IsReady() == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
-    }
+void CAudioIO::resume() {
+    if (!__mIsInit || !IsReady())
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); //LCOV_EXCL_LINE
 
     try {
         internalLock();
         AUDIO_IO_LOGD("resume");
         mpPulseAudioClient->cork(false);
         internalUnlock();
-    } catch (CAudioError e) {
+    } catch (const CAudioError& e) {
         internalUnlock();
-        throw e;
+        throw;
     }
 }
 
-void CAudioIO::drain() throw (CAudioError) {
-    if (__mIsInit == false || IsReady() == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
-    }
+void CAudioIO::drain() {
+    if (!__mIsInit || !IsReady())
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); //LCOV_EXCL_LINE
 
     try {
-        internalLock();
-        AUDIO_IO_LOGD("drain");
-        mpPulseAudioClient->drain();
-        internalUnlock();
-    } catch (CAudioError e) {
-        internalUnlock();
-        throw e;
+        if (mpPulseAudioClient->isInThread()) {
+            mpPulseAudioClient->drain();
+        } else {
+            internalLock();
+            mpPulseAudioClient->drain();
+            internalUnlock();
+        }
+    } catch (const CAudioError& e) {
+        if (!mpPulseAudioClient->isInThread())
+            internalUnlock();
+        throw;
     }
 }
 
-void CAudioIO::flush() throw (CAudioError) {
-    if (__mIsInit == false || IsReady() == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
-    }
+void CAudioIO::flush() {
+    if (!__mIsInit || !IsReady())
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); //LCOV_EXCL_LINE
 
     try {
-        internalLock();
-        AUDIO_IO_LOGD("flush");
-        mpPulseAudioClient->flush();
-        internalUnlock();
-    } catch (CAudioError e) {
-        internalUnlock();
-        throw e;
+        if (mpPulseAudioClient->isInThread()) {
+            mpPulseAudioClient->flush();
+        } else {
+            internalLock();
+            mpPulseAudioClient->flush();
+            internalUnlock();
+        }
+    } catch (const CAudioError& e) {
+        if (!mpPulseAudioClient->isInThread())
+            internalUnlock();
+        throw;
     }
 }
 
-CAudioInfo& CAudioIO::getAudioInfo() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+CAudioInfo& CAudioIO::getAudioInfo() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 
     return mAudioInfo;
 }
 
-void CAudioIO::setStreamCallback(SStreamCallback callback) throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+void CAudioIO::setStreamCallback(SStreamCallback callback) {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 
     mStreamCallback = callback;
 }
 
-CAudioIO::SStreamCallback CAudioIO::getStreamCallback() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+CAudioIO::SStreamCallback CAudioIO::getStreamCallback() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 
     return mStreamCallback;
 }
 
-void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 
     mStateChangedCallback = callback;
 }
 
-CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() {
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 
     return mStateChangedCallback;
 }
 
-void CAudioIO::setInterruptCallback(SInterruptCallback callback) throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) {
+    if (!stream_info)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_ARGUMENT, "stream_info is NULL"); //LCOV_EXCL_LINE
 
-    mInterruptCallback = callback;
-}
-
-CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+    if (!__mIsInit)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
 
-    return mInterruptCallback;
-}
-
-
-void CAudioIO::ignoreSession() throw (CAudioError) {
-    if (__mIsInit == false) {
-        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
+    if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started"); //LCOV_EXCL_LINE
 
-    try {
-        internalLock();
+    int errorCode = SOUND_MANAGER_ERROR_NONE;
+    char *type = nullptr;
+    int index = -1;
+    bool avail = false;
 
-        if (mpPulseAudioClient != NULL && mpPulseAudioClient->isCorked() == false) {
-            THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "An Operation is not permitted while started");
-        }
+    if ((errorCode = sound_manager_is_available_stream_information(stream_info, NATIVE_API_AUDIO_IO, &avail)) != SOUND_MANAGER_ERROR_NONE)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info is invalid [ret:%d]", errorCode); //LCOV_EXCL_LINE
+    if (!avail)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE, "Input stream is not supported"); //LCOV_EXCL_LINE
 
-        bool isSkip = mpAudioSessionHandler->isSkipSessionEvent();
-        if (isSkip == false && mpAudioSessionHandler->getId() >= 0) {
-            mpAudioSessionHandler->unregisterSound();
-            __mForceIgnore = true;
-        }
+    if ((errorCode = sound_manager_get_type_from_stream_information(stream_info, &type)) != SOUND_MANAGER_ERROR_NONE)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode); //LCOV_EXCL_LINE
+    if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN)
+        getAudioInfo().setAudioTypeByInputStreamType(type);
+    else
+        getAudioInfo().setAudioTypeByOutputStreamType(type);
 
-        internalUnlock();
-    } catch (CAudioError e) {
-        internalUnlock();
-        throw e;
-    }
+    if ((errorCode = sound_manager_get_index_from_stream_information(stream_info, &index)) != SOUND_MANAGER_ERROR_NONE)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->index is invalid [ret:%d]", errorCode); //LCOV_EXCL_LINE
+    getAudioInfo().setAudioIndex(index);
 }