Add to lock/unlock focus Id mutex 77/158977/1
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 2 Nov 2017 05:48:38 +0000 (14:48 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 6 Nov 2017 07:52:35 +0000 (07:52 +0000)
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 <sc11.lee@samsung.com>
include/CAudioSessionHandler.h
packaging/capi-media-audio-io.spec
src/cpp/CAudioSessionHandler.cpp

index 9aa8f0a..cd971b2 100644 (file)
@@ -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;
     };
 
index 85e4135..8e049ff 100644 (file)
@@ -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
index 771910e..b116141 100644 (file)
@@ -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<void*>(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<void*>(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();
     }
 }