Add session mutex lock
[platform/core/api/audio-io.git] / src / cpp / CAudioIO.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <mm.h>
19 #include <pthread.h>
20 #include <assert.h>
21 #include <glib.h>
22 #include "CAudioIODef.h"
23
24 using namespace std;
25 using namespace tizen_media_audio;
26
27
28 /**
29  * class CAudioIO
30  */
31 CAudioIO::CAudioIO() :
32     mpAudioSessionHandler(NULL),
33     mpPulseAudioClient(NULL),
34     __mMutex(PTHREAD_MUTEX_INITIALIZER),
35     __mSessionMutex(PTHREAD_MUTEX_INITIALIZER),
36     __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
37     __mCond(PTHREAD_COND_INITIALIZER),
38     __mIsInit(false),
39     __mForceIgnore(false) {
40     mInterruptCode = IAudioSessionEventListener::EInterruptCode::INTERRUPT_MAX;
41     mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
42     mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
43     mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
44     mByPolicy = false;
45     mIsInterrupted = false;
46 }
47
48 CAudioIO::CAudioIO(CAudioInfo& audioInfo) :
49     mpAudioSessionHandler(NULL),
50     mpPulseAudioClient(NULL),
51     __mMutex(PTHREAD_MUTEX_INITIALIZER),
52     __mSessionMutex(PTHREAD_MUTEX_INITIALIZER),
53     __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
54     __mCond(PTHREAD_COND_INITIALIZER),
55     __mIsInit(false),
56     __mForceIgnore(false) {
57     mAudioInfo = audioInfo;
58     mInterruptCode = IAudioSessionEventListener::EInterruptCode::INTERRUPT_MAX;
59     mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
60     mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
61     mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
62     mByPolicy = false;
63     mIsInterrupted = false;
64 }
65
66 CAudioIO::~CAudioIO() {
67 }
68
69 void CAudioIO::setInit(bool flag) {
70     __mIsInit = flag;
71 }
72
73 bool CAudioIO::isInit() {
74     return __mIsInit;
75 }
76
77 bool CAudioIO::IsReady() {
78     return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING ||
79              mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED)? true : false);
80 }
81
82 void CAudioIO::internalLock() {
83     if (__mIsInit == false)
84         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
85
86     if (pthread_mutex_lock(&__mMutex) != 0)
87         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
88
89 #ifdef _AUDIO_IO_DEBUG_TIMING_
90     AUDIO_IO_LOGD(COLOR_RED "%p LOCKED" COLOR_END, &__mMutex);
91 #endif
92 }
93
94 void CAudioIO::internalUnlock() {
95     if (__mIsInit == false)
96         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
97
98     if (pthread_mutex_unlock(&__mMutex) != 0)
99         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
100
101 #ifdef _AUDIO_IO_DEBUG_TIMING_
102     AUDIO_IO_LOGD(COLOR_GREEN "%p UNLOCKED" COLOR_END, &__mMutex);
103 #endif
104 }
105
106 void CAudioIO::internalSessionLock() {
107     if (__mIsInit == false)
108         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
109
110     if (pthread_mutex_lock(&__mSessionMutex) != 0)
111         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed session pthread_mutex_lock()");
112
113 #ifdef _AUDIO_IO_DEBUG_TIMING_
114     AUDIO_IO_LOGD(COLOR_RED "%p LOCKED" COLOR_END, &__mSessionMutex);
115 #endif
116 }
117
118 void CAudioIO::internalSessionUnlock() {
119     if (__mIsInit == false)
120         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
121
122     if (pthread_mutex_unlock(&__mSessionMutex) != 0)
123         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed session pthread_mutex_unlock()");
124
125 #ifdef _AUDIO_IO_DEBUG_TIMING_
126     AUDIO_IO_LOGD(COLOR_GREEN "%p UNLOCKED" COLOR_END, &__mSessionMutex);
127 #endif
128 }
129
130
131 void CAudioIO::internalWait() {
132     if (__mIsInit == false)
133         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
134
135 #ifdef _AUDIO_IO_DEBUG_TIMING_
136     AUDIO_IO_LOGD(COLOR_RED "WAIT" COLOR_END);
137 #endif
138
139     pthread_mutex_lock(&__mCondMutex);
140     pthread_cond_wait(&__mCond, &__mCondMutex);
141     pthread_mutex_unlock(&__mCondMutex);
142 }
143
144 void CAudioIO::internalSignal() {
145     if (__mIsInit == false)
146         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
147
148 #ifdef _AUDIO_IO_DEBUG_TIMING_
149     AUDIO_IO_LOGD(COLOR_GREEN "SIGNAL" COLOR_END);
150 #endif
151
152     pthread_mutex_lock(&__mCondMutex);
153     pthread_cond_signal(&__mCond);
154     pthread_mutex_unlock(&__mCondMutex);
155 }
156
157 bool CAudioIO::isForceIgnore() {
158     return __mForceIgnore;
159 }
160
161 bool CAudioIO::isSessionEnabled() {
162     if (mpAudioSessionHandler &&
163         mpAudioSessionHandler->isSkipSession() == false &&
164         mpAudioSessionHandler->getId() >= 0)
165         return true;
166
167     return false;
168 }
169
170 void CAudioIO::initialize() {
171     if (__mIsInit == true)
172         return;
173
174     AUDIO_IO_LOGD("initialize");
175
176     int ret = pthread_mutex_init(&__mMutex, NULL);
177     if (ret != 0)
178         THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_init()");
179
180     ret = pthread_mutex_init(&__mSessionMutex, NULL);
181     if (ret != 0)
182         THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed session pthread_mutex_init()");
183
184     ret = pthread_cond_init(&__mCond, NULL);
185     if (ret != 0)
186         THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_init()");
187
188     __mIsInit = true;
189 }
190
191 void CAudioIO::finalize() {
192     if (__mIsInit == false)
193         return;
194
195     AUDIO_IO_LOGD("finalize");
196
197     bool error_occured = false;
198     int ret = pthread_mutex_destroy(&__mMutex);
199     if (ret != 0) {
200         AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mMutex, ret);
201         error_occured = true;
202     }
203
204     ret = pthread_mutex_destroy(&__mSessionMutex);
205     if (ret != 0) {
206         AUDIO_IO_LOGE("Failed session pthread_mutex_destroy(%p) errno:%d", &__mSessionMutex, ret);
207         error_occured = true;
208     }
209
210     ret = pthread_mutex_destroy(&__mCondMutex);
211     if (ret != 0) {
212         AUDIO_IO_LOGE("Failed cond pthread_mutex_destroy(%p) errno:%d", &__mCondMutex, ret);
213         error_occured = true;
214     }
215
216     ret = pthread_cond_destroy(&__mCond);
217     if (ret != 0) {
218         AUDIO_IO_LOGE("Failed pthread_cond_destroy(%p) errno:%d", &__mCond, ret);
219         error_occured = true;
220     }
221
222     if (error_occured)
223         THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Finalize Failed");
224
225     __mIsInit = false;
226 }
227
228 void CAudioIO::onStream(CPulseAudioClient* pClient, size_t length) {
229     assert(__mIsInit == true);
230     assert(pClient != NULL);
231     assert(length > 0);
232
233 #ifdef _AUDIO_IO_DEBUG_TIMING_
234     AUDIO_IO_LOGD("mStreamCallback.onStream(%p), pClient(%p), length(%zu)", mStreamCallback.onStream, pClient, length);
235 #endif
236
237     if (mStreamCallback.onStream != NULL)
238         mStreamCallback.onStream(length, mStreamCallback.mUserData);
239 }
240
241 void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) {
242     assert(__mIsInit == true);
243     assert(state >= CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE && state < CAudioInfo::EAudioIOState::AUDIO_IO_STATE_MAX);
244
245     mStatePrev = mState;
246     mState = state;
247     mByPolicy = byPolicy;
248
249     if (mState == mStatePrev)
250         return;
251
252     const char* state_string[] = { "NONE", "IDLE", "RUNNING", "PAUSED" };
253
254     AUDIO_IO_LOGD("previous(%s,%d) ===> current(%s,%d), by_policy(%d)",
255                   state_string[static_cast<int>(mStatePrev)],
256                   static_cast<int>(mStatePrev),
257                   state_string[static_cast<int>(mState)],
258                   static_cast<int>(mState),
259                   mByPolicy);
260
261     if (mStateChangedCallback.onStateChanged != NULL)
262         mStateChangedCallback.onStateChanged(mState, mStatePrev, mByPolicy, mStateChangedCallback.mUserData);
263 }
264
265 void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state) {
266     onStateChanged(state, false);
267 }
268
269 CAudioInfo::EAudioIOState CAudioIO::getState() {
270     return mState;
271 }
272
273 int CAudioIO::sendInterrupt(void* user_data) {
274     CAudioIO *pCaudioIo = (CAudioIO *)user_data;
275
276     if (pCaudioIo && pCaudioIo->mInterruptCallback.onInterrupt) {
277         AUDIO_IO_LOGD("sending interrupt [%d]", static_cast<int>(pCaudioIo->mInterruptCode));
278         pCaudioIo->mInterruptCallback.onInterrupt(pCaudioIo->mInterruptCode, pCaudioIo->mInterruptCallback.mUserData);
279     }
280     return 0;
281 }
282
283 int caudio_gsource_callback(void *user_data) {
284     CAudioIO::sendInterrupt(user_data);
285     return 0;
286 }
287
288 void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type,
289                            mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info) {
290     assert(pHandler);
291
292     int session_option = pHandler->getOptions();
293
294     if (id == -1) {
295         ///////////////////////////////////////
296         // Triggered by 'focus watch callback'
297         ///////////////////////////////////////
298
299         if (session_option & (MM_SESSION_OPTION_PAUSE_OTHERS | MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
300             AUDIO_IO_LOGD("Session option is pausing others or uninterruptible, skip...");
301             return;
302         }
303
304         if (state == FOCUS_IS_RELEASED) {
305             // Focus handle(id) of the other application was released, notify resume
306             // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
307             state = FOCUS_IS_ACQUIRED;
308         } else if (state == FOCUS_IS_ACQUIRED) {
309             // Focus handle(id) of the other application was acquired, do pause if possible
310             internalLock();
311             if (mpPulseAudioClient)
312                 mpPulseAudioClient->cork(true);
313             mIsInterrupted = true;
314             internalUnlock();
315
316             // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
317             state = FOCUS_IS_RELEASED;
318         }
319     } else {
320         ///////////////////////////////////////
321         // Triggered by 'focus callback'
322         ///////////////////////////////////////
323
324         if (pHandler->getId() != id)
325             AUDIO_IO_LOGW("Id is different, why? [mId : %d]", pHandler->getId());
326
327         if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
328             AUDIO_IO_LOGD("Session option is uninterruptible, skip...");
329             return;
330         }
331
332         if (state == FOCUS_IS_RELEASED) {
333             // Focus handle(id) was released, do pause here
334             internalLock();
335             if (mpPulseAudioClient)
336                 mpPulseAudioClient->cork(true);
337
338             mIsInterrupted = true;
339             internalUnlock();
340         } else if (state == FOCUS_IS_ACQUIRED) {
341             // Focus handle(id) was acquired again,
342             // check reason_for_change ("call-voice","call-video","voip","alarm","notification", ...)
343             // do resume here and call interrupt completed callback to application.
344         }
345     }
346
347     if (mInterruptCallback.onInterrupt != NULL) {
348         IAudioSessionEventListener::EInterruptCode e = IAudioSessionEventListener::EInterruptCode::INTERRUPT_COMPLETED;
349         e = IAudioSessionEventListener::convertInterruptedCode(state, reason_for_change);
350
351         if (EInterruptCode::INTERRUPT_COMPLETED == e) {
352             mInterruptCode = e;
353             g_idle_add(caudio_gsource_callback, this);
354         } else {
355             mInterruptCallback.onInterrupt(e, mInterruptCallback.mUserData);
356         }
357     }
358 }
359
360 void CAudioIO::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) {
361     assert(pHandler);
362
363     if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
364         if (value == 1 && pHandler->getSubscribeId() > 0) {
365             // Unregister focus watch callback & disable session handler
366             pHandler->disableSessionHandler();
367             AUDIO_IO_LOGD("Session handler disabled by signal");
368         } else if (value == 0) {
369             // Currently do nothing...
370         }
371     }
372 }
373
374 void CAudioIO::prepare() {
375     if (__mIsInit == false)
376         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
377
378     try {
379         if (mIsInterrupted) {
380             internalSessionLock();
381             AUDIO_IO_LOGE("This is preparing during interrupted!!!");
382             if (isSessionEnabled() && __mForceIgnore == false) {
383                 AUDIO_IO_LOGE("Session updatePlaying!!!");
384                 mpAudioSessionHandler->updatePlaying();
385             }
386             internalSessionUnlock();
387         }
388     } catch (CAudioError& e) {
389         internalSessionUnlock();
390         throw;
391     }
392
393     if (mIsInterrupted) {
394         if (mpPulseAudioClient && mpPulseAudioClient->isCorked()) {
395             AUDIO_IO_LOGE("Uncork!");
396             mpPulseAudioClient->cork(false);
397         }
398         mIsInterrupted = false;
399     }
400 }
401
402 void CAudioIO::unprepare() {
403     if (__mIsInit == false)
404         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
405 }
406
407 void CAudioIO::pause() {
408     if (__mIsInit == false || IsReady() == false)
409         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
410
411     try {
412         internalLock();
413         AUDIO_IO_LOGD("pause");
414         mpPulseAudioClient->cork(true);
415         internalUnlock();
416     } catch (CAudioError& e) {
417         internalUnlock();
418         throw;
419     }
420 }
421
422 void CAudioIO::resume() {
423     if (__mIsInit == false || IsReady() == false)
424         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
425
426     try {
427         internalLock();
428         AUDIO_IO_LOGD("resume");
429         mpPulseAudioClient->cork(false);
430         internalUnlock();
431     } catch (CAudioError& e) {
432         internalUnlock();
433         throw;
434     }
435 }
436
437 void CAudioIO::drain() {
438     if (__mIsInit == false || IsReady() == false)
439         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
440
441     try {
442         if (mpPulseAudioClient->isInThread()) {
443             mpPulseAudioClient->drain();
444         } else {
445             internalLock();
446             mpPulseAudioClient->drain();
447             internalUnlock();
448         }
449     } catch (CAudioError& e) {
450         if (!mpPulseAudioClient->isInThread())
451             internalUnlock();
452         throw;
453     }
454 }
455
456 void CAudioIO::flush() {
457     if (__mIsInit == false || IsReady() == false)
458         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
459
460     try {
461         if (mpPulseAudioClient->isInThread()) {
462             mpPulseAudioClient->flush();
463         } else {
464             internalLock();
465             mpPulseAudioClient->flush();
466             internalUnlock();
467         }
468     } catch (CAudioError& e) {
469         if (!mpPulseAudioClient->isInThread())
470             internalUnlock();
471         throw;
472     }
473 }
474
475 CAudioInfo& CAudioIO::getAudioInfo() {
476     if (__mIsInit == false)
477         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
478
479     return mAudioInfo;
480 }
481
482 void CAudioIO::setStreamCallback(SStreamCallback callback) {
483     if (__mIsInit == false)
484         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
485
486     mStreamCallback = callback;
487 }
488
489 CAudioIO::SStreamCallback CAudioIO::getStreamCallback() {
490     if (__mIsInit == false)
491         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
492
493     return mStreamCallback;
494 }
495
496 void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) {
497     if (__mIsInit == false)
498         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
499
500     mStateChangedCallback = callback;
501 }
502
503 CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() {
504     if (__mIsInit == false)
505         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
506
507     return mStateChangedCallback;
508 }
509
510 void CAudioIO::setInterruptCallback(SInterruptCallback callback) {
511     if (__mIsInit == false)
512         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
513
514     mInterruptCallback = callback;
515 }
516
517 CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() {
518     if (__mIsInit == false)
519         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
520
521     return mInterruptCallback;
522 }
523
524 void CAudioIO::ignoreSession() {
525     if (__mIsInit == false)
526         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
527
528     try {
529         internalLock();
530         if (mpPulseAudioClient != NULL && mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING)
531             THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_OPERATION, "An Operation is not permitted while started");
532
533         abandonInternalFocus();
534         internalUnlock();
535     } catch (CAudioError& e) {
536         internalUnlock();
537         throw;
538     }
539 }
540
541 void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) {
542     if (stream_info == NULL)
543         THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_ARGUMENT, "stream_info is NULL");
544
545     if (__mIsInit == false)
546         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
547
548     try {
549         if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE)
550             THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started");
551
552         abandonInternalFocus();
553
554         int errorCode = SOUND_MANAGER_ERROR_NONE;
555         CAudioInfo::EAudioType audioType = CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA;
556         char *type = NULL;
557         int index = -1;
558         bool avail = false;
559
560         if ((errorCode = sound_manager_is_available_stream_information(stream_info, NATIVE_API_AUDIO_IO, &avail)) != SOUND_MANAGER_ERROR_NONE)
561             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info is invalid [ret:%d]", errorCode);
562         if (!avail)
563             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE, "Input stream is not supported");
564
565         if ((errorCode = sound_manager_get_type_from_stream_information(stream_info, &type)) != SOUND_MANAGER_ERROR_NONE)
566             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode);
567         if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN)
568             getAudioInfo().convertInputStreamType2AudioType(type, &audioType);
569         else
570             getAudioInfo().convertOutputStreamType2AudioType(type, &audioType);
571         getAudioInfo().setAudioType(audioType);
572
573         if ((errorCode = sound_manager_get_index_from_stream_information(stream_info, &index)) != SOUND_MANAGER_ERROR_NONE)
574             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->index is invalid [ret:%d]", errorCode);
575         getAudioInfo().setAudioIndex(index);
576
577     } catch (CAudioError& e) {
578         throw;
579     }
580 }
581
582 void CAudioIO::setInternalStreamInfo() {
583     if (__mIsInit == false)
584         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
585
586     if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE)
587         THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started");
588
589     sound_stream_info_h stream_info = NULL;
590
591     try {
592         internalSessionLock();
593         if (mpAudioSessionHandler &&
594             mpAudioSessionHandler->getMultimediaSession() == MM_SESSION_TYPE_VOIP) {
595             mpAudioSessionHandler->getInternalVoipStreamInfo(&stream_info);
596             AUDIO_IO_LOGD("get internal VOIP stream info(%p)", stream_info);
597         }
598         internalSessionUnlock();
599     } catch (CAudioError& e) {
600         internalSessionUnlock();
601         throw;
602     }
603
604     /* NOTE: to avoid double-lock, this should be outside of try-catch. */
605     if (stream_info)
606         setStreamInfo(stream_info);
607 }
608
609 void CAudioIO::abandonInternalFocus() {
610     try {
611         internalSessionLock();
612         if (isSessionEnabled()) {
613             mpAudioSessionHandler->unregisterSound();
614             mpAudioSessionHandler->finalize();  /* FIXME : SAFE_FINALIZE or SAFE_DELETE? */
615         }
616         __mForceIgnore = true;
617         internalSessionUnlock();
618     } catch (CAudioError& e) {
619         internalSessionUnlock();
620         throw;
621     }
622 }