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