From 0ccb20925e6e9de1d10623f1ea3bcd05bf9c399c Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Thu, 2 Nov 2017 14:48:38 +0900 Subject: [PATCH] Add to lock/unlock focus Id mutex There are cases that focus or focus watch callback is used internally for session backward compatibility. Because there has not been any mutex for focus id, sometimes an unintended error happens accessed from another thread. Now, a mutex for the focus id is added and operated to secure the critical section. [Version] 0.4.3 [Issue Type] Bug fix Change-Id: Ib4c721f49e80417a6b92e19e1bf61c81148bb1d4 Signed-off-by: Sangchul Lee --- include/CAudioSessionHandler.h | 3 ++ packaging/capi-media-audio-io.spec | 2 +- src/cpp/CAudioSessionHandler.cpp | 60 ++++++++++++++++++++++++++++++++++---- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/include/CAudioSessionHandler.h b/include/CAudioSessionHandler.h index 9aa8f0a..cd971b2 100644 --- a/include/CAudioSessionHandler.h +++ b/include/CAudioSessionHandler.h @@ -116,6 +116,8 @@ namespace tizen_media_audio { CAudioError __getAsmInformation(MMSessionType *type, int *options); bool __isFocusRequired(MMSessionType type, int options); bool __isFocusDisableReacquisitionRequired(MMSessionType type, int options); + void __lockFocusIdMutex(); + void __unlockFocusIdMutex(); void __lockFocusCBMutex(); void __unlockFocusCBMutex(); bool __checkNeedBlock(const char *focus_acquired_by); @@ -143,6 +145,7 @@ namespace tizen_media_audio { char* __mReasonForChange; /* For audio focus */ char* __mAdditionalInfo; /* For audio focus */ + pthread_mutex_t __mFocusIdMutex; pthread_mutex_t __mFocusCBMutex; }; diff --git a/packaging/capi-media-audio-io.spec b/packaging/capi-media-audio-io.spec index 85e4135..8e049ff 100644 --- a/packaging/capi-media-audio-io.spec +++ b/packaging/capi-media-audio-io.spec @@ -1,6 +1,6 @@ Name: capi-media-audio-io Summary: An Audio Input & Audio Output library in Tizen Native API -Version: 0.4.2 +Version: 0.4.3 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/cpp/CAudioSessionHandler.cpp b/src/cpp/CAudioSessionHandler.cpp index 771910e..b116141 100644 --- a/src/cpp/CAudioSessionHandler.cpp +++ b/src/cpp/CAudioSessionHandler.cpp @@ -81,9 +81,27 @@ int CAudioSessionHandler::__focusIdCountGet() { return __sFocusRef; } +void CAudioSessionHandler::__lockFocusIdMutex() { + if (pthread_mutex_lock(&__mFocusIdMutex) != 0) { + THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock() - FocusId Mutex"); + } +#ifdef _AUDIO_IO_DEBUG_TIMING_ + AUDIO_IO_LOGD(COLOR_RED "LOCK - FocusId Mutex" COLOR_END); +#endif +} + +void CAudioSessionHandler::__unlockFocusIdMutex() { + if (pthread_mutex_unlock(&__mFocusIdMutex) != 0) { + THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_unlock() - FocusId Mutex"); + } +#ifdef _AUDIO_IO_DEBUG_TIMING_ + AUDIO_IO_LOGD(COLOR_GREEN "UNLOCK - FocusId Mutex" COLOR_END); +#endif +} + void CAudioSessionHandler::__lockFocusCBMutex() { if (pthread_mutex_lock(&__mFocusCBMutex) != 0) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()"); + THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock() - FocusCB Mutex"); } #ifdef _AUDIO_IO_DEBUG_TIMING_ AUDIO_IO_LOGD(COLOR_RED "LOCK - FocusCB Mutex" COLOR_END); @@ -92,7 +110,7 @@ void CAudioSessionHandler::__lockFocusCBMutex() { void CAudioSessionHandler::__unlockFocusCBMutex() { if (pthread_mutex_unlock(&__mFocusCBMutex) != 0) { - THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_unlock()"); + THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_unlock() - FocusCB Mutex"); } #ifdef _AUDIO_IO_DEBUG_TIMING_ AUDIO_IO_LOGD(COLOR_GREEN "UNLOCK - FocusCB Mutex" COLOR_END); @@ -111,6 +129,7 @@ CAudioSessionHandler::CAudioSessionHandler(EAudioSessionType sessionType, CAudio __mAcquiredFocus(FOCUS_NONE), __mReasonForChange(NULL), __mAdditionalInfo(NULL), + __mFocusIdMutex(PTHREAD_MUTEX_INITIALIZER), __mFocusCBMutex(PTHREAD_MUTEX_INITIALIZER) { __mAudioInfo = audioInfo; } @@ -389,7 +408,9 @@ void CAudioSessionHandler::registerSound() { } if (__mUseFocus == true) { + __lockFocusIdMutex(); if (__mId >= 0) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Already registered [id:%d]", __mId); } @@ -400,11 +421,13 @@ void CAudioSessionHandler::registerSound() { CAudioError err = __convertStreamType(__mAudioSession, __mMultimediaSession, &index); if (err != CAudioError::EError::ERROR_NONE) { + __unlockFocusIdMutex(); throw err; } errorCode = mm_sound_focus_get_id(&__mId); if (errorCode != MM_ERROR_NONE) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_focus_get_id() err:0x%x", errorCode); } @@ -415,12 +438,14 @@ void CAudioSessionHandler::registerSound() { __sound_pcm_focus_cb, static_cast(this)); if (errorCode != MM_ERROR_NONE) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_register_focus_for_session() err:0x%x", errorCode); } if (__isFocusDisableReacquisitionRequired(__mMultimediaSession, __mOptions)) { errorCode = mm_sound_set_focus_reacquisition_for_session(__mId, false); if (errorCode != MM_ERROR_NONE) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_set_focus_reacquisition() err:0x%x", errorCode); } } @@ -432,6 +457,7 @@ void CAudioSessionHandler::registerSound() { // Register focus watch callback errorCode = mm_sound_set_focus_watch_callback_for_session(getpid(), FOCUS_FOR_BOTH, __sound_pcm_focus_watch_cb, static_cast(this), &__mId); if (errorCode < 0) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_set_focus_watch_callback_for_session() err:0x%x", errorCode); } @@ -439,6 +465,7 @@ void CAudioSessionHandler::registerSound() { AUDIO_IO_LOGD("Focus watch callback registered successfully [id:%d]", __mId); } + __unlockFocusIdMutex(); } } @@ -447,6 +474,7 @@ void CAudioSessionHandler::unregisterSound() { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler"); } + __lockFocusIdMutex(); if (__mUseFocus == true && __mId >= 0) { int errorCode = 0; @@ -454,6 +482,7 @@ void CAudioSessionHandler::unregisterSound() { // Unregister focus callback errorCode = mm_sound_unregister_focus(__mId); if (errorCode != MM_ERROR_NONE) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_unregister_focus() err:0x%x", errorCode); } @@ -465,6 +494,7 @@ void CAudioSessionHandler::unregisterSound() { // Unregister focus watch callback. errorCode = mm_sound_unset_focus_watch_callback(__mId); if (errorCode < 0) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_unset_focus_watch_callback() err:0x%x", errorCode); } @@ -475,14 +505,18 @@ void CAudioSessionHandler::unregisterSound() { } __mAcquiredFocus = FOCUS_NONE; } + __unlockFocusIdMutex(); } void CAudioSessionHandler::updatePlaying() { if (__mIsInit == false) { THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler"); } - if (!__mUseFocus || __mId < 0) + __lockFocusIdMutex(); + if (!__mUseFocus || __mId < 0) { + __unlockFocusIdMutex(); return; + } if (__mUseFocus && __isFocusRequired(__mMultimediaSession, __mOptions)) { if (__mId >= 0) { @@ -490,8 +524,10 @@ void CAudioSessionHandler::updatePlaying() { int focus_type = 0; bool is_focus_cb_thread; - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed mm_sound_focus_is_cb_thread() err:0x%x", ret); + } if (!is_focus_cb_thread) __lockFocusCBMutex(); @@ -500,6 +536,7 @@ void CAudioSessionHandler::updatePlaying() { AUDIO_IO_LOGW("Focus was already acquired, skip it..."); if (!is_focus_cb_thread) __unlockFocusCBMutex(); + __unlockFocusIdMutex(); return; } @@ -511,6 +548,7 @@ void CAudioSessionHandler::updatePlaying() { if (ret != MM_ERROR_NONE) { if (!is_focus_cb_thread) __unlockFocusCBMutex(); + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_acquire_focus() err:0x%x", ret); } __mAcquiredFocus = FOCUS_FOR_BOTH; @@ -525,19 +563,23 @@ void CAudioSessionHandler::updatePlaying() { char *ext_info = NULL; int option = 0; - if ((ret = mm_sound_get_stream_type_of_acquired_focus(FOCUS_FOR_BOTH, &stream_type, &option, &ext_info))) + if ((ret = mm_sound_get_stream_type_of_acquired_focus(FOCUS_FOR_BOTH, &stream_type, &option, &ext_info))) { + __unlockFocusIdMutex(); return; + } AUDIO_IO_LOGD("Focus is acquired by stream_type[%s], option[%d], ext_info[%s]", stream_type, option, ext_info); if (__checkNeedBlock((const char*)stream_type)) { free(stream_type); free(ext_info); + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Blocked by an acquired focus"); } free(stream_type); free(ext_info); } + __unlockFocusIdMutex(); } void CAudioSessionHandler::updateStop() { @@ -546,12 +588,15 @@ void CAudioSessionHandler::updateStop() { } if (__mUseFocus && __isFocusRequired(__mMultimediaSession, __mOptions)) { + __lockFocusIdMutex(); if (__mId >= 0) { int ret = MM_ERROR_NONE; bool is_focus_cb_thread; - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) { + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed mm_sound_focus_is_cb_thread() err:0x%x", ret); + } if (!is_focus_cb_thread) __lockFocusCBMutex(); @@ -560,6 +605,7 @@ void CAudioSessionHandler::updateStop() { AUDIO_IO_LOGW("Focus was already released, skip it..."); if (!is_focus_cb_thread) __unlockFocusCBMutex(); + __unlockFocusIdMutex(); return; } @@ -570,6 +616,7 @@ void CAudioSessionHandler::updateStop() { if (ret != MM_ERROR_NONE) { if (!is_focus_cb_thread) __unlockFocusCBMutex(); + __unlockFocusIdMutex(); THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed mm_sound_release_focus() err:0x%x", ret); } __mAcquiredFocus = FOCUS_NONE; @@ -578,6 +625,7 @@ void CAudioSessionHandler::updateStop() { if (!is_focus_cb_thread) __unlockFocusCBMutex(); } + __unlockFocusIdMutex(); } } -- 2.7.4