From ccae6d61826f1b7f5ced92b99d256fb38d3137e7 Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Fri, 22 Mar 2019 10:44:43 +0900 Subject: [PATCH] Return error of acquiring/releasing focus in focus watch callback when the previous request is in progress [Version] 0.5.21 [Issue Type] Enhancement Change-Id: Ic78f6f13024de8f604570f35ca5e28f8a07f3ee6 Signed-off-by: Sangchul Lee --- include/sound_manager_private.h | 1 + packaging/capi-media-sound-manager.spec | 2 +- src/sound_manager.c | 54 +++++++++++++++++++++---- src/sound_manager_private.c | 4 +- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/include/sound_manager_private.h b/include/sound_manager_private.h index 30aa35d..1c72fc4 100644 --- a/include/sound_manager_private.h +++ b/include/sound_manager_private.h @@ -199,6 +199,7 @@ typedef struct _sound_stream_info_s { int focus_id; char *stream_type; bool is_focus_unavailable; + bool is_requesting; pa_threaded_mainloop *pa_mainloop; pa_context *pa_context; stream_conf_info_s stream_conf_info; diff --git a/packaging/capi-media-sound-manager.spec b/packaging/capi-media-sound-manager.spec index 9a02108..916073b 100644 --- a/packaging/capi-media-sound-manager.spec +++ b/packaging/capi-media-sound-manager.spec @@ -1,6 +1,6 @@ Name: capi-media-sound-manager Summary: Sound Manager library -Version: 0.5.20 +Version: 0.5.21 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/sound_manager.c b/src/sound_manager.c index 626017f..acbde74 100644 --- a/src/sound_manager.c +++ b/src/sound_manager.c @@ -273,13 +273,14 @@ int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_fo { int ret = MM_ERROR_NONE; bool is_focus_cb_thread = false; + bool is_focus_watch_cb_thread = false; sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info; LOGI(">> enter"); SM_INSTANCE_CHECK(stream_h); - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread))) return _convert_sound_manager_error_code(__func__, ret); if (stream_h->is_focus_unavailable) { @@ -296,6 +297,12 @@ int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_fo SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL); SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL); } else { + /* If it is inside of the watch cb and if the previous request of this process has not been finished yet, + * the focus state mutex could be still locked. Therefore, it returns error here. */ + if (is_focus_watch_cb_thread && stream_h->is_requesting) { + LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet"); + return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION); + } SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL); } @@ -312,6 +319,8 @@ int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_fo goto LEAVE; } + stream_h->is_requesting = true; + ret = mm_sound_acquire_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info); if (ret == MM_ERROR_NONE) { stream_h->acquired_focus |= focus_mask; @@ -322,6 +331,7 @@ int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_fo LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus); LEAVE: + stream_h->is_requesting = false; SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex); if (!is_focus_cb_thread) SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex); @@ -333,19 +343,26 @@ int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_fo { int ret = MM_ERROR_NONE; bool is_focus_cb_thread = false; + bool is_focus_watch_cb_thread = false; sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info; LOGI(">> enter"); SM_INSTANCE_CHECK(stream_h); - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread))) return _convert_sound_manager_error_code(__func__, ret); if (!is_focus_cb_thread) { SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL); SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL); } else { + /* If it is inside of the watch cb and if the previous request of this process has not been finished yet, + * the focus state mutex could be still locked. Therefore, it returns error here. */ + if (is_focus_watch_cb_thread && stream_h->is_requesting) { + LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet"); + return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION); + } SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL); } @@ -362,6 +379,8 @@ int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_fo goto LEAVE; } + stream_h->is_requesting = true; + ret = mm_sound_release_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info); if (ret == MM_ERROR_NONE) { stream_h->acquired_focus &= ~focus_mask; @@ -372,6 +391,7 @@ int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_fo LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus); LEAVE: + stream_h->is_requesting = false; SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex); if (!is_focus_cb_thread) SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex); @@ -384,13 +404,14 @@ int sound_manager_acquire_focus_all(sound_stream_info_h stream_info, int sound_b int ret = MM_ERROR_NONE; int focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH; bool is_focus_cb_thread = false; + bool is_focus_watch_cb_thread = false; sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info; LOGI(">> enter"); SM_INSTANCE_CHECK(stream_h); - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread))) return _convert_sound_manager_error_code(__func__, ret); if (stream_h->is_focus_unavailable) { @@ -407,6 +428,12 @@ int sound_manager_acquire_focus_all(sound_stream_info_h stream_info, int sound_b SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL); SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL); } else { + /* If it is inside of the watch cb and if the previous request of this process has not been finished yet, + * the focus state mutex could be still locked. Therefore, it returns error here. */ + if (is_focus_watch_cb_thread && stream_h->is_requesting) { + LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet"); + return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION); + } SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL); } @@ -424,6 +451,8 @@ int sound_manager_acquire_focus_all(sound_stream_info_h stream_info, int sound_b goto LEAVE; } + stream_h->is_requesting = true; + ret = mm_sound_acquire_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info); if (ret == MM_ERROR_NONE) { stream_h->acquired_focus |= focus_mask; @@ -432,6 +461,7 @@ int sound_manager_acquire_focus_all(sound_stream_info_h stream_info, int sound_b } LEAVE: + stream_h->is_requesting = false; SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex); if (!is_focus_cb_thread) SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex); @@ -443,19 +473,26 @@ int sound_manager_release_focus_all(sound_stream_info_h stream_info, int sound_b { int ret = MM_ERROR_NONE; bool is_focus_cb_thread = false; + bool is_focus_watch_cb_thread = false; sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info; LOGI(">> enter"); SM_INSTANCE_CHECK(stream_h); - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread))) return _convert_sound_manager_error_code(__func__, ret); if (!is_focus_cb_thread) { SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL); SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL); } else { + /* If it is inside of the watch cb and if the previous request of this process has not been finished yet, + * the focus state mutex could be still locked. Therefore, it returns error here. */ + if (is_focus_watch_cb_thread && stream_h->is_requesting) { + LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet"); + return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION); + } SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL); } @@ -472,6 +509,8 @@ int sound_manager_release_focus_all(sound_stream_info_h stream_info, int sound_b goto LEAVE; } + stream_h->is_requesting = true; + ret = mm_sound_release_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)stream_h->acquired_focus, sound_behavior, extra_info); if (ret == MM_ERROR_NONE) { stream_h->acquired_focus = 0; @@ -480,6 +519,7 @@ int sound_manager_release_focus_all(sound_stream_info_h stream_info, int sound_b } LEAVE: + stream_h->is_requesting = false; SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex); if (!is_focus_cb_thread) SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex); @@ -524,7 +564,7 @@ int sound_manager_deliver_focus(sound_stream_info_h source, sound_stream_info_h SM_INSTANCE_CHECK(src_stream_h); SM_INSTANCE_CHECK(dst_stream_h); - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL))) return _convert_sound_manager_error_code(__func__, ret); if (is_focus_cb_thread) { @@ -607,7 +647,7 @@ int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e SM_NULL_ARG_CHECK(acquired_by); SM_NULL_ARG_CHECK(flags); - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL))) return _convert_sound_manager_error_code(__func__, ret); if (is_focus_cb_thread) { @@ -645,7 +685,7 @@ int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e SM_NULL_ARG_CHECK(acquired_by); SM_NULL_ARG_CHECK(flags); - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL))) return _convert_sound_manager_error_code(__func__, ret); if (is_focus_cb_thread) { diff --git a/src/sound_manager_private.c b/src/sound_manager_private.c index 2fbc44c..0258faf 100644 --- a/src/sound_manager_private.c +++ b/src/sound_manager_private.c @@ -1910,7 +1910,7 @@ int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_ int i = 0; bool is_focus_cb_thread = false; - if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread))) + if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL))) return ret; if (is_focus_cb_thread) @@ -2008,7 +2008,7 @@ int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h) int ret = MM_ERROR_NONE; bool is_focus_cb_thread = false; - ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread); + ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL); if (ret) return ret; -- 2.34.1