Fix build warning
[platform/core/api/audio-io.git] / src / cpp / CAudioIO.cpp
index e1dd7a2..0de125b 100644 (file)
 #include <mm.h>
 #include <pthread.h>
 #include <assert.h>
+#include <glib.h>
 #include "CAudioIODef.h"
 
-#define AUDIO_IO_DEBUG
-
 using namespace std;
 using namespace tizen_media_audio;
 
@@ -33,25 +32,33 @@ CAudioIO::CAudioIO() :
     mpAudioSessionHandler(NULL),
     mpPulseAudioClient(NULL),
     __mMutex(PTHREAD_MUTEX_INITIALIZER),
+    __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
     __mCond(PTHREAD_COND_INITIALIZER),
     __mIsInit(false),
     __mForceIgnore(false) {
+    mInterruptCode = IAudioSessionEventListener::EInterruptCode::INTERRUPT_MAX;
+    mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
     mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mByPolicy = false;
+    mIsInterrupted = false;
 }
 
 CAudioIO::CAudioIO(CAudioInfo& audioInfo) :
     mpAudioSessionHandler(NULL),
     mpPulseAudioClient(NULL),
     __mMutex(PTHREAD_MUTEX_INITIALIZER),
+    __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
     __mCond(PTHREAD_COND_INITIALIZER),
     __mIsInit(false),
     __mForceIgnore(false) {
     mAudioInfo = audioInfo;
+    mInterruptCode = IAudioSessionEventListener::EInterruptCode::INTERRUPT_MAX;
+    mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
     mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
     mByPolicy = false;
+    mIsInterrupted = false;
 }
 
 CAudioIO::~CAudioIO() {
@@ -69,7 +76,7 @@ bool CAudioIO::IsReady() {
     return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING || mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED)? true : false);
 }
 
-void CAudioIO::internalLock() throw(CAudioError) {
+void CAudioIO::internalLock() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -77,12 +84,13 @@ void CAudioIO::internalLock() throw(CAudioError) {
     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) {
+void CAudioIO::internalUnlock() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -91,11 +99,11 @@ void CAudioIO::internalUnlock() throw(CAudioError) {
         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) {
+void CAudioIO::internalWait() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -104,10 +112,12 @@ void CAudioIO::internalWait() throw(CAudioError) {
     AUDIO_IO_LOGD(COLOR_RED "WAIT" COLOR_END);
 #endif
 
-    pthread_cond_wait(&__mCond, &__mMutex);
+    pthread_mutex_lock(&__mCondMutex);
+    pthread_cond_wait(&__mCond, &__mCondMutex);
+    pthread_mutex_unlock(&__mCondMutex);
 }
 
-void CAudioIO::internalSignal() throw(CAudioError) {
+void CAudioIO::internalSignal() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -116,14 +126,16 @@ void CAudioIO::internalSignal() throw(CAudioError) {
     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) {
+void CAudioIO::initialize() {
     if (__mIsInit == true) {
         return;
     }
@@ -150,16 +162,28 @@ void CAudioIO::finalize() {
 
     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);
+        AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mMutex, ret);
+        error_occured = true;
+    }
+    ret = pthread_mutex_destroy(&__mCondMutex);
+    if (ret != 0) {
+        AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mCondMutex, ret);
+        error_occured = true;
     }
 
+
     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);
+        AUDIO_IO_LOGE("Failed pthread_cond_destroy(%p) errno:%d", &__mCond, ret);
+        error_occured = true;
     }
 
+    if (error_occured)
+        THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Finalize Failed");
+
     __mIsInit = false;
 }
 
@@ -188,7 +212,14 @@ void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) {
     if (mState == mStatePrev)
         return;
 
-    AUDIO_IO_LOGD("current(%d), previous(%d), by_policy(%d)", mState, mStatePrev, mByPolicy);
+    const char* state_string[] = { "NONE", "IDLE", "RUNNING", "PAUSED" };
+
+    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) {
         mStateChangedCallback.onStateChanged(mState, mStatePrev, mByPolicy, mStateChangedCallback.mUserData);
@@ -199,7 +230,27 @@ 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) {
+CAudioInfo::EAudioIOState CAudioIO::getState() {
+    return mState;
+}
+
+int CAudioIO::sendInterrupt(void* user_data) {
+    CAudioIO *pCaudioIo = (CAudioIO *)user_data;
+
+    if (pCaudioIo && pCaudioIo->mInterruptCallback.onInterrupt) {
+        AUDIO_IO_LOGD("sending interrupt [%d]", static_cast<int>(pCaudioIo->mInterruptCode));
+        pCaudioIo->mInterruptCallback.onInterrupt(pCaudioIo->mInterruptCode, pCaudioIo->mInterruptCallback.mUserData);
+    }
+    return 0;
+}
+
+int caudio_gsource_callback(void *user_data) {
+    CAudioIO::sendInterrupt(user_data);
+    return 0;
+}
+
+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();
@@ -215,29 +266,16 @@ void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focu
         }
 
         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 handle(id) of the other application was released, notify resume
             // 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()");
-                }
+            if (mpPulseAudioClient) {
+                mpPulseAudioClient->cork(true);
             }
-
-            mpPulseAudioClient->cork(true);
-            onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED);
-
+            mIsInterrupted = true;
             internalUnlock();
 
             // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
@@ -260,34 +298,29 @@ void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focu
         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()");
-                }
+            if (mpPulseAudioClient) {
+                mpPulseAudioClient->cork(true);
             }
 
-            mpPulseAudioClient->cork(true);
-            onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED);
-
+            mIsInterrupted = true;
             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);
+
+        if (EInterruptCode::INTERRUPT_COMPLETED == e) {
+            mInterruptCode = e;
+            g_idle_add(caudio_gsource_callback, this);
+        } else {
+            mInterruptCallback.onInterrupt(e, mInterruptCallback.mUserData);
+        }
     }
 }
 
@@ -295,7 +328,7 @@ void CAudioIO::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t s
     assert(pHandler);
 
     if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
-        if (value == 1 && pHandler->getSubscribeId() >= 0) {
+        if (value == 1 && pHandler->getSubscribeId() > 0) {
             // Unregister focus watch callback & disable session handler
             pHandler->disableSessionHandler();
             AUDIO_IO_LOGD("Session handler disabled by signal");
@@ -305,33 +338,52 @@ void CAudioIO::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t s
     }
 }
 
-void CAudioIO::prepare() throw(CAudioError) {
+void CAudioIO::prepare() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
-
+    if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN) {
+        AUDIO_IO_LOGD("Prepare for Audio in");
+    } else if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_OUT) {
+        AUDIO_IO_LOGD("Prepare for Audio Out");
+    }
     try {
-        AUDIO_IO_LOGD("prepare");
+        if (mIsInterrupted) {
+            AUDIO_IO_LOGE("This is preparing during interrupted!!!");
+            bool isSkip = mpAudioSessionHandler->isSkipSession();
+            if (__mForceIgnore == false && isSkip == false && mpAudioSessionHandler->getId() >= 0) {
+                AUDIO_IO_LOGE("Session updatePlaying!!!");
+                mpAudioSessionHandler->updatePlaying();
+            }
+
+            if (mpPulseAudioClient && mpPulseAudioClient->isCorked()) {
+                AUDIO_IO_LOGE("Uncork!");
+                mpPulseAudioClient->cork(false);
+            }
+            mIsInterrupted = false;
+        }
+
+        AUDIO_IO_LOGD("------> prepare done");
         /* Do nothing */
-    } catch (CAudioError e) {
-        throw e;
+    } catch (CAudioError& e) {
+        throw;
     }
 }
 
-void CAudioIO::unprepare() throw(CAudioError) {
+void CAudioIO::unprepare() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
 
     try {
-        AUDIO_IO_LOGD("unprepare");
+        AUDIO_IO_LOGD("unprepare ----->");
         /* Do nothing */
-    } catch (CAudioError e) {
-        throw e;
+    } catch (CAudioError& e) {
+        throw;
     }
 }
 
-void CAudioIO::pause() throw(CAudioError) {
+void CAudioIO::pause() {
     if (__mIsInit == false || IsReady() == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
     }
@@ -341,13 +393,13 @@ void CAudioIO::pause() throw(CAudioError) {
         AUDIO_IO_LOGD("pause");
         mpPulseAudioClient->cork(true);
         internalUnlock();
-    } catch (CAudioError e) {
+    } catch (CAudioError& e) {
         internalUnlock();
-        throw e;
+        throw;
     }
 }
 
-void CAudioIO::resume() throw(CAudioError) {
+void CAudioIO::resume() {
     if (__mIsInit == false || IsReady() == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
     }
@@ -357,45 +409,55 @@ void CAudioIO::resume() throw(CAudioError) {
         AUDIO_IO_LOGD("resume");
         mpPulseAudioClient->cork(false);
         internalUnlock();
-    } catch (CAudioError e) {
+    } catch (CAudioError& e) {
         internalUnlock();
-        throw e;
+        throw;
     }
 }
 
-void CAudioIO::drain() throw(CAudioError) {
+void CAudioIO::drain() {
     if (__mIsInit == false || IsReady() == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
     }
 
     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 (CAudioError& e) {
+        if (!mpPulseAudioClient->isInThread()) {
+            internalUnlock();
+        }
+        throw;
     }
 }
 
-void CAudioIO::flush() throw(CAudioError) {
+void CAudioIO::flush() {
     if (__mIsInit == false || IsReady() == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
     }
 
     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 (CAudioError& e) {
+        if (!mpPulseAudioClient->isInThread()) {
+            internalUnlock();
+        }
+        throw;
     }
 }
 
-CAudioInfo& CAudioIO::getAudioInfo() throw(CAudioError) {
+CAudioInfo& CAudioIO::getAudioInfo() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -403,7 +465,7 @@ CAudioInfo& CAudioIO::getAudioInfo() throw(CAudioError) {
     return mAudioInfo;
 }
 
-void CAudioIO::setStreamCallback(SStreamCallback callback) throw(CAudioError) {
+void CAudioIO::setStreamCallback(SStreamCallback callback) {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -411,7 +473,7 @@ void CAudioIO::setStreamCallback(SStreamCallback callback) throw(CAudioError) {
     mStreamCallback = callback;
 }
 
-CAudioIO::SStreamCallback CAudioIO::getStreamCallback() throw(CAudioError) {
+CAudioIO::SStreamCallback CAudioIO::getStreamCallback() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -419,7 +481,7 @@ CAudioIO::SStreamCallback CAudioIO::getStreamCallback() throw(CAudioError) {
     return mStreamCallback;
 }
 
-void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) throw(CAudioError) {
+void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -427,7 +489,7 @@ void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) throw(CAu
     mStateChangedCallback = callback;
 }
 
-CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() throw(CAudioError) {
+CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -435,7 +497,7 @@ CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() throw(CAudio
     return mStateChangedCallback;
 }
 
-void CAudioIO::setInterruptCallback(SInterruptCallback callback) throw(CAudioError) {
+void CAudioIO::setInterruptCallback(SInterruptCallback callback) {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -443,7 +505,7 @@ void CAudioIO::setInterruptCallback(SInterruptCallback callback) throw(CAudioErr
     mInterruptCallback = callback;
 }
 
-CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() throw(CAudioError) {
+CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() {
     if (__mIsInit == false) {
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
     }
@@ -451,28 +513,101 @@ CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() throw(CAudioError)
     return mInterruptCallback;
 }
 
-
-void CAudioIO::ignoreSession() throw(CAudioError) {
-    if (__mIsInit == false) {
+void CAudioIO::ignoreSession() {
+    if (__mIsInit == false)
         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
-    }
 
     try {
         internalLock();
 
-        if (mpPulseAudioClient != NULL && mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING) {
+        if (mpPulseAudioClient != NULL && mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING)
             THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "An Operation is not permitted while started");
-        }
 
-        bool isSkip = mpAudioSessionHandler->isSkipSessionEvent();
-        if (isSkip == false && mpAudioSessionHandler->getId() >= 0) {
-            mpAudioSessionHandler->unregisterSound();
-            __mForceIgnore = true;
-        }
+        abandonInternalFocus();
 
         internalUnlock();
-    } catch (CAudioError e) {
+    } catch (CAudioError& e) {
         internalUnlock();
-        throw e;
+        throw;
+    }
+}
+
+void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) {
+    if (stream_info == NULL)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_ARGUMENT, "stream_info is NULL");
+
+    if (__mIsInit == false)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+
+    try {
+        if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE)
+            THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started");
+
+        abandonInternalFocus();
+
+        int errorCode = SOUND_MANAGER_ERROR_NONE;
+        CAudioInfo::EAudioType audioType = CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA;
+        char *type = NULL;
+        int index = -1;
+        bool avail = false;
+
+        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);
+
+        if (!avail)
+            THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE, "Input stream is not supported");
+
+        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);
+
+        if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN)
+            getAudioInfo().convertInputStreamType2AudioType(type, &audioType);
+        else
+            getAudioInfo().convertOutputStreamType2AudioType(type, &audioType);
+        getAudioInfo().setAudioType(audioType);
+
+        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);
+
+        getAudioInfo().setAudioIndex(index);
+
+        AUDIO_IO_LOGD("stream info(%p) is set", stream_info);
+    } catch (CAudioError& e) {
+        throw;
+    }
+}
+
+void CAudioIO::setInternalStreamInfo() {
+    if (__mIsInit == false)
+        THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+
+    try {
+        if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE)
+            THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started");
+
+        if (mpAudioSessionHandler &&
+            mpAudioSessionHandler->getMultimediaSession() == MM_SESSION_TYPE_VOIP) {
+            sound_stream_info_h stream_info = NULL;
+            mpAudioSessionHandler->getInternalVoipStreamInfo(&stream_info);
+            AUDIO_IO_LOGD("get internal VOIP stream info(%p)", stream_info);
+            setStreamInfo(stream_info);
+        }
+    } catch (CAudioError& e) {
+        throw;
+    }
+}
+
+void CAudioIO::abandonInternalFocus() {
+    bool isSkip = mpAudioSessionHandler->isSkipSession();
+    int id = mpAudioSessionHandler->getId();
+
+    try {
+        if (isSkip == false && id >= 0)
+            mpAudioSessionHandler->unregisterSound();
+
+        mpAudioSessionHandler->finalize();
+        __mForceIgnore = true;
+    } catch (CAudioError& e) {
+        throw;
     }
 }