Add to lock/unlock focus Id mutex
[platform/core/api/audio-io.git] / src / cpp / CAudioSessionHandler.cpp
index f56d73e..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;
 }
@@ -186,6 +205,22 @@ bool CAudioSessionHandler::__isFocusDisableReacquisitionRequired(MMSessionType t
     return false;
 }
 
+bool CAudioSessionHandler::__checkNeedBlock(const char *focus_acquired_by) {
+    assert(focus_acquired_by != NULL);
+
+    if (!strcmp(focus_acquired_by, "alarm") ||
+        !strcmp(focus_acquired_by, "ringtone-voip") ||
+        !strcmp(focus_acquired_by, "ringtone-call") ||
+        !strcmp(focus_acquired_by, "voip") ||
+        !strcmp(focus_acquired_by, "call-voice") ||
+        !strcmp(focus_acquired_by, "call-video")) {
+        AUDIO_IO_LOGW("Blocked by session policy, focus_acquired_by[%s]", focus_acquired_by);
+        return true;
+    }
+
+    return false;
+}
+
 int CAudioSessionHandler::getId() {
     return __mId;
 }
@@ -373,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);
         }
 
@@ -384,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);
             }
 
@@ -399,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);
                 }
             }
@@ -416,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);
             }
 
@@ -423,6 +465,7 @@ void CAudioSessionHandler::registerSound() {
 
             AUDIO_IO_LOGD("Focus watch callback registered successfully [id:%d]", __mId);
         }
+        __unlockFocusIdMutex();
     }
 }
 
@@ -431,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;
 
@@ -438,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);
             }
 
@@ -449,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);
             }
 
@@ -459,12 +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");
     }
+    __lockFocusIdMutex();
+    if (!__mUseFocus || __mId < 0) {
+        __unlockFocusIdMutex();
+        return;
+    }
 
     if (__mUseFocus && __isFocusRequired(__mMultimediaSession, __mOptions)) {
         if (__mId >= 0) {
@@ -472,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();
@@ -482,6 +536,7 @@ void CAudioSessionHandler::updatePlaying() {
                 AUDIO_IO_LOGW("Focus was already acquired, skip it...");
                 if (!is_focus_cb_thread)
                     __unlockFocusCBMutex();
+                __unlockFocusIdMutex();
                 return;
             }
 
@@ -493,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;
@@ -501,7 +557,29 @@ void CAudioSessionHandler::updatePlaying() {
             if (!is_focus_cb_thread)
                 __unlockFocusCBMutex();
         }
+    } else {
+        int ret = MM_ERROR_NONE;
+        char *stream_type = NULL;
+        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))) {
+            __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() {
@@ -510,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();
@@ -524,6 +605,7 @@ void CAudioSessionHandler::updateStop() {
                 AUDIO_IO_LOGW("Focus was already released, skip it...");
                 if (!is_focus_cb_thread)
                     __unlockFocusCBMutex();
+                __unlockFocusIdMutex();
                 return;
             }
 
@@ -534,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;
@@ -542,6 +625,7 @@ void CAudioSessionHandler::updateStop() {
             if (!is_focus_cb_thread)
                 __unlockFocusCBMutex();
         }
+        __unlockFocusIdMutex();
     }
 }