b116141a5ad3c93494508586c384d689314d4b79
[platform/core/api/audio-io.git] / src / cpp / CAudioSessionHandler.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 <unistd.h>
19 #include <mm_error.h>
20 #include "CAudioIODef.h"
21
22
23 using namespace std;
24 using namespace tizen_media_audio;
25
26
27 /**
28  * class CAudioSessionHandler
29  */
30 int CAudioSessionHandler::__sCaptureRef = 0;
31
32 int CAudioSessionHandler::__pcmCaptureCountInc() {
33     int actual;
34     do {
35         actual = __sCaptureRef;
36     } while (!__sync_bool_compare_and_swap(&__sCaptureRef, actual, actual + 1));
37     AUDIO_IO_LOGD("CaptureRefCount+1 > [%d]", __sCaptureRef);
38     return __sCaptureRef;
39 }
40
41 int CAudioSessionHandler::__pcmCaptureCountDec() {
42     int actual;
43     do {
44         actual = __sCaptureRef;
45     } while (!__sync_bool_compare_and_swap(&__sCaptureRef, actual, actual - 1));
46     AUDIO_IO_LOGD("CaptureRefCount-1 > [%d]", __sCaptureRef);
47     if (__sCaptureRef < 0) {
48         AUDIO_IO_LOGE("A CaptureRef[%d] is not valid! Something is wrong!", __sCaptureRef);
49         __sCaptureRef = 0;
50     }
51     return __sCaptureRef;
52 }
53
54 int CAudioSessionHandler::__pcmCaptureCountGet() {
55     AUDIO_IO_LOGD("CaptureRefCount > [%d]", __sCaptureRef);
56     return __sCaptureRef;
57 }
58
59 int CAudioSessionHandler::__sFocusRef = 0;
60
61 int CAudioSessionHandler::__focusIdCountInc() {
62     int actual;
63     do {
64         actual = __sFocusRef;
65     } while (!__sync_bool_compare_and_swap(&__sFocusRef, actual, actual + 1));
66     AUDIO_IO_LOGD("FocusRefCount+1 > [%d]", __sFocusRef);
67     return __sFocusRef;
68 }
69
70 int CAudioSessionHandler::__focusIdCountDec() {
71     int actual;
72     do {
73         actual = __sFocusRef;
74     } while (!__sync_bool_compare_and_swap(&__sFocusRef, actual, actual - 1));
75     AUDIO_IO_LOGD("FocusRefCount-1 > [%d]", __sFocusRef);
76     return __sFocusRef;
77 }
78
79 int CAudioSessionHandler::__focusIdCountGet() {
80     /* AUDIO_IO_LOGD("FocusRefCount > [%d]", __sFocusRef); */
81     return __sFocusRef;
82 }
83
84 void CAudioSessionHandler::__lockFocusIdMutex() {
85     if (pthread_mutex_lock(&__mFocusIdMutex) != 0) {
86         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock() - FocusId Mutex");
87     }
88 #ifdef _AUDIO_IO_DEBUG_TIMING_
89     AUDIO_IO_LOGD(COLOR_RED "LOCK - FocusId Mutex" COLOR_END);
90 #endif
91 }
92
93 void CAudioSessionHandler::__unlockFocusIdMutex() {
94     if (pthread_mutex_unlock(&__mFocusIdMutex) != 0) {
95         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_unlock() - FocusId Mutex");
96     }
97 #ifdef _AUDIO_IO_DEBUG_TIMING_
98     AUDIO_IO_LOGD(COLOR_GREEN "UNLOCK - FocusId Mutex" COLOR_END);
99 #endif
100 }
101
102 void CAudioSessionHandler::__lockFocusCBMutex() {
103     if (pthread_mutex_lock(&__mFocusCBMutex) != 0) {
104         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock() - FocusCB Mutex");
105     }
106 #ifdef _AUDIO_IO_DEBUG_TIMING_
107     AUDIO_IO_LOGD(COLOR_RED "LOCK - FocusCB Mutex" COLOR_END);
108 #endif
109 }
110
111 void CAudioSessionHandler::__unlockFocusCBMutex() {
112     if (pthread_mutex_unlock(&__mFocusCBMutex) != 0) {
113         THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_unlock() - FocusCB Mutex");
114     }
115 #ifdef _AUDIO_IO_DEBUG_TIMING_
116     AUDIO_IO_LOGD(COLOR_GREEN "UNLOCK - FocusCB Mutex" COLOR_END);
117 #endif
118 }
119
120 CAudioSessionHandler::CAudioSessionHandler(EAudioSessionType sessionType, CAudioInfo& audioInfo, IAudioSessionEventListener* listener) :
121     __mId(-1),
122     __mOptions(0),
123     __mAudioSession(sessionType),
124     __mMultimediaSession(MM_SESSION_TYPE_MEDIA),
125     __mpEventListener(listener),
126     __mIsInit(false),
127     __mSubscribeId(0),
128     __mUseFocus(false),
129     __mAcquiredFocus(FOCUS_NONE),
130     __mReasonForChange(NULL),
131     __mAdditionalInfo(NULL),
132     __mFocusIdMutex(PTHREAD_MUTEX_INITIALIZER),
133     __mFocusCBMutex(PTHREAD_MUTEX_INITIALIZER) {
134     __mAudioInfo = audioInfo;
135 }
136
137 CAudioSessionHandler::~CAudioSessionHandler() {
138 }
139
140 CAudioError CAudioSessionHandler::__convertStreamType(EAudioSessionType type1, MMSessionType type2, int *index) {
141     unsigned int i;
142     int idx = -1;
143
144     assert(index != NULL);
145
146     if (type1 == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE) {
147         for (i = 0 ; i < sizeof(__STREAM_TYPE_TABLE_IN) / sizeof(__STREAM_TYPE_TABLE_IN[0]) ; i++) {
148             if (__STREAM_TYPE_TABLE_IN[i].type == type2) {
149                 idx = i;
150                 break;
151             }
152         }
153     } else {
154         for (i = 0 ; i < sizeof(__STREAM_TYPE_TABLE_OUT) / sizeof(__STREAM_TYPE_TABLE_OUT[0]) ; i++) {
155             if (__STREAM_TYPE_TABLE_OUT[i].type == type2) {
156                 idx = i;
157                 break;
158             }
159         }
160     }
161
162     if (idx < 0) {
163         RET_ERROR_MSG(CAudioError::EError::ERROR_NOT_SUPPORTED, "Does not support session type.");
164     }
165     *index = idx;
166     RET_ERROR(CAudioError::EError::ERROR_NONE);
167 }
168
169 CAudioError CAudioSessionHandler::__getAsmInformation(MMSessionType *type, int *options) {
170     assert(type != NULL);
171     assert(options != NULL);
172
173     MMSessionType currentSession = MM_SESSION_TYPE_MEDIA;
174     int           sessionOptions = 0;
175
176     /* Read session information */
177     int ret = 0;
178     if ((ret = _mm_session_util_read_information(-1, (int*)&currentSession, &sessionOptions)) < 0) {
179         if (ret == (int) MM_ERROR_INVALID_HANDLE) {
180             RET_ERROR_MSG(CAudioError::EError::ERROR_INVALID_HANDLE, "Failed _mm_session_util_read_information(). Invalid handle");
181         } else {
182             RET_ERROR_MSG(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed _mm_session_util_read_information(). Not exist");
183         }
184     }
185
186     *type    = currentSession;
187     *options = sessionOptions;
188
189     RET_ERROR(CAudioError::EError::ERROR_NONE);
190 }
191
192 bool CAudioSessionHandler::__isFocusRequired(MMSessionType type, int options) {
193     if ((options & MM_SESSION_OPTION_PAUSE_OTHERS)
194         || ((type != MM_SESSION_TYPE_MEDIA) && (type != MM_SESSION_TYPE_MEDIA_RECORD)))
195         return true;
196     else
197         return false;
198 }
199
200 bool CAudioSessionHandler::__isFocusDisableReacquisitionRequired(MMSessionType type, int options) {
201     if ((type == MM_SESSION_TYPE_MEDIA) &&
202         !(options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED))
203         return true;
204
205     return false;
206 }
207
208 bool CAudioSessionHandler::__checkNeedBlock(const char *focus_acquired_by) {
209     assert(focus_acquired_by != NULL);
210
211     if (!strcmp(focus_acquired_by, "alarm") ||
212         !strcmp(focus_acquired_by, "ringtone-voip") ||
213         !strcmp(focus_acquired_by, "ringtone-call") ||
214         !strcmp(focus_acquired_by, "voip") ||
215         !strcmp(focus_acquired_by, "call-voice") ||
216         !strcmp(focus_acquired_by, "call-video")) {
217         AUDIO_IO_LOGW("Blocked by session policy, focus_acquired_by[%s]", focus_acquired_by);
218         return true;
219     }
220
221     return false;
222 }
223
224 int CAudioSessionHandler::getId() {
225     return __mId;
226 }
227
228 int CAudioSessionHandler::getOptions() {
229     return __mOptions;
230 }
231
232 CAudioSessionHandler::EAudioSessionType CAudioSessionHandler::getAudioSession() {
233     return __mAudioSession;
234 }
235
236 MMSessionType CAudioSessionHandler::getMultimediaSession() {
237     return __mMultimediaSession;
238 }
239
240 void CAudioSessionHandler::getInternalVoipStreamInfo(sound_stream_info_h *stream_info) {
241     int ret;
242
243     if ((ret = sound_manager_get_internal_voip_stream_information(stream_info))) {
244         if (ret == SOUND_MANAGER_ERROR_NO_DATA) {
245             AUDIO_IO_LOGW("there's no internal voip stream info.");
246         } else {
247             AUDIO_IO_LOGE("failed to sound_manager_get_internal_voip_stream_information(), ret(0x%x)", ret);
248         }
249     }
250     return;
251 }
252
253 unsigned int CAudioSessionHandler::getSubscribeId() {
254     return __mSubscribeId;
255 }
256
257 CAudioInfo CAudioSessionHandler::getAudioInfo() {
258     return __mAudioInfo;
259 }
260
261 void CAudioSessionHandler::__sound_pcm_signal_cb(mm_sound_signal_name_t signal, int value, void *user_data) {
262     assert(user_data);
263
264     AUDIO_IO_LOGD("[signal:%d], [value:%d], [user_data:%p]", signal, value, user_data);
265
266     CAudioSessionHandler* pHandler = static_cast<CAudioSessionHandler*>(user_data);
267     if (pHandler->__mpEventListener != NULL)
268         pHandler->__mpEventListener->onSignal(pHandler, signal, value);
269 }
270
271 void CAudioSessionHandler::initialize() {
272     AUDIO_IO_LOGD("");
273     if (__mIsInit == true) {
274         return;
275     }
276
277     MMSessionType currentSession = MM_SESSION_TYPE_MEDIA;
278     int           sessionOptions = 0;  // Mix with others by default
279
280     CAudioError err = __getAsmInformation(&currentSession, &sessionOptions);
281     if (err == CAudioError::EError::ERROR_NONE) {
282         if (currentSession == MM_SESSION_TYPE_REPLACED_BY_STREAM) {
283             __mUseFocus = false;
284             AUDIO_IO_LOGD("Stream info. was created outside, skip audio focus concept internally!");
285         } else {
286             // Session was configured before, use focus callback
287             __mUseFocus = true;
288             AUDIO_IO_LOGD("Use audio focus concept internally!");
289         }
290     } else {
291         if (err == CAudioError::EError::ERROR_INVALID_HANDLE) {
292             // No session, No stream_info, No focus watch callback before
293             // Use focus watch callback with signal subscribe
294
295             int errorCode = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &__mSubscribeId, __sound_pcm_signal_cb, static_cast<void*>(this));
296             if (errorCode != MM_ERROR_NONE || __mSubscribeId == 0) {
297                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_subscribe_signal() err:0x%x, __mSubscribeId:%u",
298                                        errorCode, __mSubscribeId);
299             }
300
301             AUDIO_IO_LOGD("Subscribed mm_sound signal [id:%d]", __mSubscribeId);
302
303             sessionOptions = 0;  // Mix with others by default
304             __mUseFocus = true;
305             AUDIO_IO_LOGD("Use audio focus(watch) concept internally!");
306         } else {
307             __mUseFocus = false;
308             AUDIO_IO_LOGD("Skip audio focus concept!");
309         }
310
311         if (__mAudioSession == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE) {
312             AUDIO_IO_LOGD("Set default \"Media_Record\" type");
313             currentSession = MM_SESSION_TYPE_MEDIA_RECORD;
314         } else {
315             AUDIO_IO_LOGD("Set default \"Media\" type");
316             currentSession = MM_SESSION_TYPE_MEDIA;
317         }
318     }
319
320     // Updates session information
321     __mMultimediaSession = currentSession;
322     __mOptions           = sessionOptions;
323
324     if (this->__mAudioSession == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE) {
325         __pcmCaptureCountInc();
326     }
327
328     __mIsInit = true;
329 }
330
331 void CAudioSessionHandler::finalize() {
332     AUDIO_IO_LOGD("");
333     if (__mIsInit == false) {
334         return;
335     }
336
337     if (__mAudioSession == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE) {
338         __pcmCaptureCountDec();
339     }
340
341     unregisterSound();
342
343     if (__mSubscribeId > 0) {
344         AUDIO_IO_LOGD("Unsubscribed mm_sound signal [id:%d]", __mSubscribeId);
345         mm_sound_unsubscribe_signal(__mSubscribeId);
346         __mSubscribeId = 0;
347     }
348
349     __mpEventListener = NULL;
350
351     __mIsInit = false;
352 }
353
354 bool CAudioSessionHandler::isSkipSession() {
355     if (__mMultimediaSession == MM_SESSION_TYPE_REPLACED_BY_STREAM ||
356         __mMultimediaSession == MM_SESSION_TYPE_VOIP ||
357         __mMultimediaSession == MM_SESSION_TYPE_CALL ||
358         __mMultimediaSession == MM_SESSION_TYPE_VIDEOCALL) {
359         AUDIO_IO_LOGD("__mMultimediaSession is [%d], skip session", __mMultimediaSession);
360         return true;
361     }
362
363     return false;
364 }
365
366 void CAudioSessionHandler::__sound_pcm_focus_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state,
367                                                 const char *reason_for_change, int option, const char *additional_info, void *user_data) {
368     assert(user_data);
369
370     AUDIO_IO_LOGD("[id:%d], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s], [user_data:%p]",
371                   id, focus_type, state, reason_for_change, additional_info, user_data);
372
373 /* FIXME: disable it temporarily */
374 #ifndef DISABLE_SESSION_BACK_COMP
375
376     CAudioSessionHandler* pHandler = static_cast<CAudioSessionHandler*>(user_data);
377
378     pHandler->__lockFocusCBMutex();
379
380     if (state == FOCUS_IS_RELEASED)
381         pHandler->__mAcquiredFocus &= ~focus_type;
382     else if (state == FOCUS_IS_ACQUIRED)
383         pHandler->__mAcquiredFocus |= focus_type;
384     pHandler->__mReasonForChange = (char *)reason_for_change;
385     pHandler->__mAdditionalInfo  = (char *)additional_info;
386
387     if (pHandler->__mpEventListener != NULL)
388         pHandler->__mpEventListener->onInterrupt(pHandler, id, focus_type, state, reason_for_change, additional_info);
389
390     pHandler->__unlockFocusCBMutex();
391 #endif
392     return;
393 }
394
395 void CAudioSessionHandler::__sound_pcm_focus_watch_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state,
396                                                       const char *reason_for_change, const char *additional_info, void *user_data) {
397     AUDIO_IO_LOGD("[id:%d], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s], [user_data:%p]",
398                   id, focus_type, state, reason_for_change, additional_info, user_data);
399
400     CAudioSessionHandler::__sound_pcm_focus_cb(-1, focus_type, state, reason_for_change, 0, additional_info, user_data);
401
402     return;
403 }
404
405 void CAudioSessionHandler::registerSound() {
406     if (__mIsInit == false) {
407         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
408     }
409
410     if (__mUseFocus == true) {
411         __lockFocusIdMutex();
412         if (__mId >= 0) {
413             __unlockFocusIdMutex();
414             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Already registered [id:%d]", __mId);
415         }
416
417         int errorCode = 0;
418
419         if (__isFocusRequired(__mMultimediaSession, __mOptions)) {
420             int index = 0;
421
422             CAudioError err = __convertStreamType(__mAudioSession, __mMultimediaSession, &index);
423             if (err != CAudioError::EError::ERROR_NONE) {
424                 __unlockFocusIdMutex();
425                 throw err;
426             }
427
428             errorCode = mm_sound_focus_get_id(&__mId);
429             if (errorCode != MM_ERROR_NONE) {
430                 __unlockFocusIdMutex();
431                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_focus_get_id() err:0x%x", errorCode);
432             }
433
434             // Register focus callback
435             errorCode = mm_sound_register_focus_for_session(__mId,
436                                                 getpid(),
437                                                 __mAudioSession == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE ? __STREAM_TYPE_TABLE_IN[index].name : __STREAM_TYPE_TABLE_OUT[index].name,
438                                                 __sound_pcm_focus_cb,
439                                                 static_cast<void*>(this));
440             if (errorCode != MM_ERROR_NONE) {
441                 __unlockFocusIdMutex();
442                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_register_focus_for_session() err:0x%x", errorCode);
443             }
444
445             if (__isFocusDisableReacquisitionRequired(__mMultimediaSession, __mOptions)) {
446                 errorCode = mm_sound_set_focus_reacquisition_for_session(__mId, false);
447                 if (errorCode != MM_ERROR_NONE) {
448                     __unlockFocusIdMutex();
449                     THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_set_focus_reacquisition() err:0x%x", errorCode);
450                 }
451             }
452
453             __focusIdCountInc();
454
455             AUDIO_IO_LOGD("Focus callback registered successfully [id:%d]", __mId);
456         } else if (!(__mOptions & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
457             // Register focus watch callback
458             errorCode = mm_sound_set_focus_watch_callback_for_session(getpid(), FOCUS_FOR_BOTH, __sound_pcm_focus_watch_cb, static_cast<void*>(this), &__mId);
459             if (errorCode < 0) {
460                 __unlockFocusIdMutex();
461                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_set_focus_watch_callback_for_session() err:0x%x", errorCode);
462             }
463
464             __focusIdCountInc();
465
466             AUDIO_IO_LOGD("Focus watch callback registered successfully [id:%d]", __mId);
467         }
468         __unlockFocusIdMutex();
469     }
470 }
471
472 void CAudioSessionHandler::unregisterSound() {
473     if (__mIsInit == false) {
474         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
475     }
476
477     __lockFocusIdMutex();
478     if (__mUseFocus == true && __mId >= 0) {
479         int errorCode = 0;
480
481         if (__isFocusRequired(__mMultimediaSession, __mOptions)) {
482             // Unregister focus callback
483             errorCode = mm_sound_unregister_focus(__mId);
484             if (errorCode != MM_ERROR_NONE) {
485                 __unlockFocusIdMutex();
486                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_unregister_focus() err:0x%x", errorCode);
487             }
488
489             __focusIdCountDec();
490
491             AUDIO_IO_LOGD("Focus callback unregistered successfully [id:%d]", __mId);
492             __mId = -1;
493         } else if (!(__mOptions & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
494             // Unregister focus watch callback.
495             errorCode = mm_sound_unset_focus_watch_callback(__mId);
496             if (errorCode < 0) {
497                 __unlockFocusIdMutex();
498                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_unset_focus_watch_callback() err:0x%x", errorCode);
499             }
500
501             __focusIdCountDec();
502
503             AUDIO_IO_LOGD("Focus watch callback unregistered successfully [id:%d]", __mId);
504             __mId = -1;
505         }
506         __mAcquiredFocus = FOCUS_NONE;
507     }
508     __unlockFocusIdMutex();
509 }
510
511 void CAudioSessionHandler::updatePlaying() {
512     if (__mIsInit == false) {
513         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
514     }
515     __lockFocusIdMutex();
516     if (!__mUseFocus || __mId < 0) {
517         __unlockFocusIdMutex();
518         return;
519     }
520
521     if (__mUseFocus && __isFocusRequired(__mMultimediaSession, __mOptions)) {
522         if (__mId >= 0) {
523             int ret = MM_ERROR_NONE;
524             int focus_type = 0;
525             bool is_focus_cb_thread;
526
527             if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) {
528                 __unlockFocusIdMutex();
529                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed mm_sound_focus_is_cb_thread() err:0x%x", ret);
530             }
531
532             if (!is_focus_cb_thread)
533                 __lockFocusCBMutex();
534
535             if (__mAcquiredFocus == FOCUS_FOR_BOTH) {
536                 AUDIO_IO_LOGW("Focus was already acquired, skip it...");
537                 if (!is_focus_cb_thread)
538                     __unlockFocusCBMutex();
539                 __unlockFocusIdMutex();
540                 return;
541             }
542
543             focus_type |= (FOCUS_FOR_BOTH & ~__mAcquiredFocus);
544             if (__mMultimediaSession == MM_SESSION_TYPE_MEDIA)
545                 ret = mm_sound_acquire_focus_with_option(__mId, (mm_sound_focus_type_e)focus_type, 1, "audio-io acquire focus"); /* option: 1 for no-resume */
546             else
547                 ret = mm_sound_acquire_focus(__mId, (mm_sound_focus_type_e)focus_type, "audio-io acquire focus");
548             if (ret != MM_ERROR_NONE) {
549                 if (!is_focus_cb_thread)
550                     __unlockFocusCBMutex();
551                 __unlockFocusIdMutex();
552                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_acquire_focus() err:0x%x", ret);
553             }
554             __mAcquiredFocus = FOCUS_FOR_BOTH;
555             AUDIO_IO_LOGD("Focus acquired successfully [id:%d]", __mId);
556
557             if (!is_focus_cb_thread)
558                 __unlockFocusCBMutex();
559         }
560     } else {
561         int ret = MM_ERROR_NONE;
562         char *stream_type = NULL;
563         char *ext_info = NULL;
564         int option = 0;
565
566         if ((ret = mm_sound_get_stream_type_of_acquired_focus(FOCUS_FOR_BOTH, &stream_type, &option, &ext_info))) {
567             __unlockFocusIdMutex();
568             return;
569         }
570
571         AUDIO_IO_LOGD("Focus is acquired by stream_type[%s], option[%d], ext_info[%s]", stream_type, option, ext_info);
572
573         if (__checkNeedBlock((const char*)stream_type)) {
574             free(stream_type);
575             free(ext_info);
576             __unlockFocusIdMutex();
577             THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Blocked by an acquired focus");
578         }
579         free(stream_type);
580         free(ext_info);
581     }
582     __unlockFocusIdMutex();
583 }
584
585 void CAudioSessionHandler::updateStop() {
586     if (__mIsInit == false) {
587         THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
588     }
589
590     if (__mUseFocus && __isFocusRequired(__mMultimediaSession, __mOptions)) {
591         __lockFocusIdMutex();
592         if (__mId >= 0) {
593             int ret = MM_ERROR_NONE;
594             bool is_focus_cb_thread;
595
596             if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) {
597                 __unlockFocusIdMutex();
598                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed mm_sound_focus_is_cb_thread() err:0x%x", ret);
599             }
600
601             if (!is_focus_cb_thread)
602                 __lockFocusCBMutex();
603
604             if (__mAcquiredFocus == FOCUS_NONE) {
605                 AUDIO_IO_LOGW("Focus was already released, skip it...");
606                 if (!is_focus_cb_thread)
607                     __unlockFocusCBMutex();
608                 __unlockFocusIdMutex();
609                 return;
610             }
611
612             if (__mMultimediaSession == MM_SESSION_TYPE_MEDIA)
613                 ret = mm_sound_release_focus_with_option(__mId, (mm_sound_focus_type_e)__mAcquiredFocus, 1, "audio-io release focus"); /* option: 1 for no-resume */
614             else
615                 ret = mm_sound_release_focus(__mId, (mm_sound_focus_type_e)__mAcquiredFocus, "audio-io release focus");
616             if (ret != MM_ERROR_NONE) {
617                 if (!is_focus_cb_thread)
618                     __unlockFocusCBMutex();
619                 __unlockFocusIdMutex();
620                 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_release_focus() err:0x%x", ret);
621             }
622             __mAcquiredFocus = FOCUS_NONE;
623             AUDIO_IO_LOGD("Focus released successfully [id:%d]", __mId);
624
625             if (!is_focus_cb_thread)
626                 __unlockFocusCBMutex();
627         }
628         __unlockFocusIdMutex();
629     }
630 }
631
632 void CAudioSessionHandler::disableSessionHandler() {
633     CAudioSessionHandler::updateStop();
634     CAudioSessionHandler::unregisterSound();
635
636     CAudioSessionHandler::__mUseFocus = false;
637 }
638
639 /**
640  * class IAudioSessionEventListener
641  */
642 IAudioSessionEventListener::EInterruptCode IAudioSessionEventListener::convertInterruptedCode(int code, const char *reason_for_change) {
643     EInterruptCode e = EInterruptCode::INTERRUPT_BY_MEDIA;
644
645     switch (code) {
646     case FOCUS_IS_ACQUIRED:
647         e = EInterruptCode::INTERRUPT_COMPLETED;
648         break;
649
650     case FOCUS_IS_RELEASED:
651         if (!strcmp(reason_for_change, "media"))              e = EInterruptCode::INTERRUPT_BY_MEDIA;
652         if (!strcmp(reason_for_change, "radio"))              e = EInterruptCode::INTERRUPT_BY_MEDIA;
653         if (!strcmp(reason_for_change, "loopback"))           e = EInterruptCode::INTERRUPT_BY_MEDIA;
654         if (!strcmp(reason_for_change, "system"))             e = EInterruptCode::INTERRUPT_BY_MEDIA;
655         if (!strcmp(reason_for_change, "alarm"))              e = EInterruptCode::INTERRUPT_BY_ALARM;
656         if (!strcmp(reason_for_change, "notification"))       e = EInterruptCode::INTERRUPT_BY_NOTIFICATION;
657         if (!strcmp(reason_for_change, "emergency"))          e = EInterruptCode::INTERRUPT_BY_EMERGENCY;
658         if (!strcmp(reason_for_change, "voice-information"))  e = EInterruptCode::INTERRUPT_BY_MEDIA;
659         if (!strcmp(reason_for_change, "voice-recognition"))  e = EInterruptCode::INTERRUPT_BY_MEDIA;
660         if (!strcmp(reason_for_change, "voice-recognition-service")) e = EInterruptCode::INTERRUPT_BY_MEDIA;
661         if (!strcmp(reason_for_change, "ringtone-voip"))      e = EInterruptCode::INTERRUPT_BY_CALL;
662         if (!strcmp(reason_for_change, "ringtone-call"))      e = EInterruptCode::INTERRUPT_BY_CALL;
663         if (!strcmp(reason_for_change, "voip"))               e = EInterruptCode::INTERRUPT_BY_CALL;
664         if (!strcmp(reason_for_change, "call-voice"))         e = EInterruptCode::INTERRUPT_BY_CALL;
665         if (!strcmp(reason_for_change, "call-video"))         e = EInterruptCode::INTERRUPT_BY_CALL;
666         break;
667     }
668
669     return e;
670 }