From: Sangchul Lee Date: Mon, 6 Mar 2017 10:02:15 +0000 (+0900) Subject: Fix codes not to destroy internal focus handle among VoIP session modes X-Git-Tag: submit/tizen_3.0/20170329.043647~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F44%2F117544%2F9;p=platform%2Fcore%2Fapi%2Fsound-manager.git Fix codes not to destroy internal focus handle among VoIP session modes [Version] 0.3.103 [Profile] Common [Issue Type] Backward compatibility Change-Id: I444f6b0a3eba3ed9478471b673f6a2f36f026995 Signed-off-by: Sangchul Lee --- diff --git a/include/sound_manager_internal.h b/include/sound_manager_internal.h index 80b8263..9dfa9d5 100644 --- a/include/sound_manager_internal.h +++ b/include/sound_manager_internal.h @@ -230,6 +230,7 @@ int sound_manager_get_index_from_stream_information(sound_stream_info_h stream_i * @retval #SOUND_MANAGER_ERROR_NONE Success * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter * @retval #SOUND_MANAGER_ERROR_NO_DATA No data + * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system * @see sound_manager_set_session_type() * @see sound_manager_set_voip_session_mode() */ diff --git a/include/sound_manager_private.h b/include/sound_manager_private.h index 0c670c8..33d4e66 100644 --- a/include/sound_manager_private.h +++ b/include/sound_manager_private.h @@ -304,6 +304,10 @@ int _start_virtual_stream(virtual_sound_stream_info_s *virtual_stream); int _stop_virtual_stream(virtual_sound_stream_info_s *virtual_stream); +int _make_progress_virtual_stream(sound_stream_info_s *stream_info, virtual_sound_stream_info_s **virtual_stream); + +int _stop_progress_virtual_stream(virtual_sound_stream_info_s *virtual_stream); + #ifdef __cplusplus } #endif diff --git a/packaging/capi-media-sound-manager.spec b/packaging/capi-media-sound-manager.spec index 2aea72e..0ad293c 100755 --- 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.3.102 +Version: 0.3.103 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/sound_manager.c b/src/sound_manager.c index 691c7ce..652ca6b 100644 --- a/src/sound_manager.c +++ b/src/sound_manager.c @@ -31,11 +31,14 @@ _session_mode_e g_cached_session_mode = -1; int g_cached_voip_device_id = -1; int g_cached_voip_device_id2 = -1; extern sound_stream_info_s *g_voip_stream_info; +extern sound_stream_info_s *g_voip_ringtone_stream_info; extern virtual_sound_stream_info_s *g_voip_vstream_h; +extern virtual_sound_stream_info_s *g_voip_ringtone_vstream_h; /* These variables will be removed when session features are deprecated. */ extern int g_stream_info_count; extern pthread_mutex_t g_stream_info_count_mutex; +pthread_mutex_t g_session_mutex; pthread_mutex_t g_interrupt_cb_mutex, g_device_info_cb_mutex, g_device_conn_cb_mutex, g_volume_cb_mutex; int sound_manager_get_max_volume(sound_type_e type, int *max) @@ -649,13 +652,16 @@ int sound_manager_set_session_type(sound_session_type_e type) break; } + SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL); + /* valid session check */ ret = mm_session_get_current_type(&cur_session); if (ret == MM_ERROR_NONE) { if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) { if (type > SOUND_SESSION_TYPE_MEDIA) { LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type); - return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL); + ret = MM_ERROR_POLICY_INTERNAL; + goto LEAVE; } } } @@ -664,28 +670,37 @@ int sound_manager_set_session_type(sound_session_type_e type) if (new_session == cur_session || ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) { LOGI("already set type=%d, ret=0x%x", type, ret); - return SOUND_MANAGER_ERROR_NONE; + goto LEAVE; } else { ret = mm_session_finish(); if (ret != MM_ERROR_NONE) - return _convert_sound_manager_error_code(__func__, ret); + goto LEAVE; g_session_interrupt_cb_table.is_registered = 0; if (cur_session == MM_SESSION_TYPE_VOIP) { + /* De-initialize regarding VoIP session */ g_cached_session_mode = -1; g_cached_voip_device_id = -1; g_cached_voip_device_id2 = -1; if (g_voip_vstream_h) { - _stop_virtual_stream(g_voip_vstream_h); - _destroy_virtual_stream(g_voip_vstream_h); + _stop_progress_virtual_stream(g_voip_vstream_h); g_voip_vstream_h = NULL; } - /*voip stream destruction*/ + if (g_voip_ringtone_vstream_h) { + _stop_progress_virtual_stream(g_voip_ringtone_vstream_h); + g_voip_ringtone_vstream_h = NULL; + } if (g_voip_stream_info) { ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info); SM_SAFE_FREE(g_voip_stream_info); if (ret != MM_ERROR_NONE) - return _convert_sound_manager_error_code(__func__, ret); + goto LEAVE; + } + if (g_voip_ringtone_stream_info) { + ret = _destroy_pa_connection_and_unregister_focus(g_voip_ringtone_stream_info); + SM_SAFE_FREE(g_voip_ringtone_stream_info); + if (ret != MM_ERROR_NONE) + goto LEAVE; } } } @@ -695,6 +710,8 @@ int sound_manager_set_session_type(sound_session_type_e type) g_session_interrupt_cb_table.is_registered = 1; LOGI("type=%d", type); +LEAVE: + SM_LEAVE_CRITICAL_SECTION(&g_session_mutex); return _convert_sound_manager_error_code(__func__, ret); } @@ -708,6 +725,8 @@ int sound_manager_get_session_type(sound_session_type_e *type) if (type == NULL) return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT); + SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INVALID_PARAMETER); + ret = mm_session_get_current_type(&cur_session); if (ret != MM_ERROR_NONE) { LOGW("session hasn't been set, setting default session"); @@ -748,6 +767,8 @@ int sound_manager_get_session_type(sound_session_type_e *type) LOGI("type=%d", *type); + SM_LEAVE_CRITICAL_SECTION(&g_session_mutex); + return SOUND_MANAGER_ERROR_NONE; } @@ -985,6 +1006,8 @@ int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode) LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__); LOGI(">> enter : mode=%d", mode); + SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL); + ret = mm_session_get_current_information(&session, &session_options); if (ret != MM_ERROR_NONE) goto LEAVE; @@ -1004,6 +1027,8 @@ int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode) LOGI("session=%d, mode=%d(0:RINGTONE 1:MIC_RCV 2:MIC_SPK 3:EAR 4:BT)", session, mode); LEAVE: + SM_LEAVE_CRITICAL_SECTION(&g_session_mutex); + return _convert_sound_manager_error_code(__func__, ret); } @@ -1014,6 +1039,9 @@ int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode) int session_options = 0; LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__); + + SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL); + if (mode == NULL) { LOGE("mode is null"); ret = MM_ERROR_INVALID_ARGUMENT; @@ -1036,6 +1064,8 @@ int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode) LOGI("session=%d, mode=%d", session, *mode); LEAVE: + SM_LEAVE_CRITICAL_SECTION(&g_session_mutex); + return _convert_sound_manager_error_code(__func__, ret); } diff --git a/src/sound_manager_internal.c b/src/sound_manager_internal.c index 3499ac3..c5e26a8 100644 --- a/src/sound_manager_internal.c +++ b/src/sound_manager_internal.c @@ -22,7 +22,11 @@ /* These variables will be removed when session features are deprecated. */ extern int g_stream_info_count; extern pthread_mutex_t g_stream_info_count_mutex; +extern pthread_mutex_t g_session_mutex; extern sound_stream_info_s *g_voip_stream_info; +extern sound_stream_info_s *g_voip_ringtone_stream_info; +extern virtual_sound_stream_info_s *g_voip_vstream_h; +extern virtual_sound_stream_info_s *g_voip_ringtone_vstream_h; #ifndef TIZEN_FEATURE_TV_PROD int sound_manager_get_max_master_volume(int *max_level) @@ -174,13 +178,24 @@ int sound_manager_get_internal_voip_stream_information(sound_stream_info_h *stre { SM_NULL_ARG_CHECK(stream_info); - if (g_voip_stream_info == NULL) { - LOGE("internal voip internal stream_info does not exist"); + SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL); + + if (g_voip_vstream_h == NULL && g_voip_ringtone_vstream_h == NULL) { + LOGE("voip mode is not set"); + SM_LEAVE_CRITICAL_SECTION(&g_session_mutex); return SOUND_MANAGER_ERROR_NO_DATA; } - LOGI("internal VoIP stream_info[%p]", g_voip_stream_info); - *stream_info = (sound_stream_info_h)g_voip_stream_info; + if (g_voip_ringtone_vstream_h) { + LOGI("ringtone mode is activated"); + *stream_info = (sound_stream_info_h)g_voip_ringtone_stream_info; + } else { + *stream_info = (sound_stream_info_h)g_voip_stream_info; + } + + LOGI("internal VoIP stream_info[%p]", *stream_info); + + SM_LEAVE_CRITICAL_SECTION(&g_session_mutex); return SOUND_MANAGER_ERROR_NONE; } diff --git a/src/sound_manager_private.c b/src/sound_manager_private.c index ca324e8..70d51ba 100644 --- a/src/sound_manager_private.c +++ b/src/sound_manager_private.c @@ -33,6 +33,7 @@ #define PA_STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS "UpdateFocusStatus" #define VCONF_PATH_PREFIX_VOLUME "file/private/sound/volume/" #define VCONF_PATH_MAX 64 +#define EXT_INFO_VOIP_SESSION "for voip session" #define CHECK_AND_SET_DEVICE(x_dst_device1, x_dst_device2, x_src_device) \ do { \ @@ -53,7 +54,9 @@ extern int g_cached_voip_device_id2; extern _focus_watch_info_s focus_watch_info_arr[SOUND_STREAM_INFO_ARR_MAX]; sound_stream_info_s *sound_stream_info_arr[SOUND_STREAM_INFO_ARR_MAX]; sound_stream_info_s *g_voip_stream_info = NULL; +sound_stream_info_s *g_voip_ringtone_stream_info = NULL; virtual_sound_stream_info_s *g_voip_vstream_h = NULL; +virtual_sound_stream_info_s *g_voip_ringtone_vstream_h = NULL; int g_stream_info_count = 0; pthread_mutex_t g_stream_info_count_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -1300,11 +1303,13 @@ void _voip_focus_state_change_callback(sound_stream_info_h stream_info, if (!(info->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) || !(info->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING)) { /* stop virtual stream for rintone-voip or voip */ + if (g_voip_ringtone_vstream_h) { + _stop_progress_virtual_stream(g_voip_ringtone_vstream_h); + g_voip_ringtone_vstream_h = NULL; + LOGW("internal voip ringtone stream is interrupted by (%d)", reason); + } if (g_voip_vstream_h) { - /* stop virtual stream handle */ - _stop_virtual_stream(g_voip_vstream_h); - /* destroy virtual stream handle */ - _destroy_virtual_stream(g_voip_vstream_h); + _stop_progress_virtual_stream(g_voip_vstream_h); g_voip_vstream_h = NULL; LOGW("internal voip stream is interrupted by (%d)", reason); } @@ -1335,45 +1340,41 @@ int _set_session_mode(_session_mode_e mode) if (mode == _SESSION_MODE_RINGTONE) { if (g_voip_vstream_h) { - /* stop vstream and destroy vstream */ - _stop_virtual_stream(g_voip_vstream_h); - _destroy_virtual_stream(g_voip_vstream_h); + _stop_progress_virtual_stream(g_voip_vstream_h); g_voip_vstream_h = NULL; - /* destroy stream info */ - _destroy_pa_connection_and_unregister_focus(g_voip_stream_info); - SM_SAFE_FREE(g_voip_stream_info); } - if (!g_voip_stream_info) { - g_voip_stream_info = malloc(sizeof(sound_stream_info_s)); - if (!g_voip_stream_info) { + if (!g_voip_ringtone_stream_info) { + g_voip_ringtone_stream_info = malloc(sizeof(sound_stream_info_s)); + if (!g_voip_ringtone_stream_info) { ret = MM_ERROR_OUT_OF_MEMORY; goto ERROR_CASE; } - memset(g_voip_stream_info, 0, sizeof(sound_stream_info_s)); - } - /* create stream info and acquire focus for rintone-voip stream */ - g_voip_stream_info->stream_type = "ringtone-voip"; - if ((ret = _make_pa_connection_and_register_focus(g_voip_stream_info, true, _voip_focus_state_change_callback, NULL))) { - SM_SAFE_FREE(g_voip_stream_info); - goto ERROR_CASE; + memset(g_voip_ringtone_stream_info, 0, sizeof(sound_stream_info_s)); + g_voip_ringtone_stream_info->stream_type = "ringtone-voip"; + if ((ret = _make_pa_connection_and_register_focus(g_voip_ringtone_stream_info, true, _voip_focus_state_change_callback, NULL))) { + SM_SAFE_FREE(g_voip_ringtone_stream_info); + goto ERROR_CASE; + } } - /* acquire focus */ - if ((ret = mm_sound_acquire_focus(g_voip_stream_info->index, FOCUS_FOR_BOTH, "for voip session"))) - goto ERROR_CASE; + if ((ret = mm_sound_acquire_focus(g_voip_ringtone_stream_info->index, FOCUS_FOR_BOTH, EXT_INFO_VOIP_SESSION))) { + if (ret != MM_ERROR_SOUND_INVALID_STATE) + goto ERROR_CASE; + LOGI("already acquired, skip it"); + ret = MM_ERROR_NONE; + } - g_voip_stream_info->acquired_focus |= FOCUS_FOR_BOTH; - _update_focus_status(g_voip_stream_info->index, (unsigned int)g_voip_stream_info->acquired_focus); + g_voip_ringtone_stream_info->acquired_focus |= FOCUS_FOR_BOTH; + _update_focus_status(g_voip_ringtone_stream_info->index, (unsigned int)g_voip_ringtone_stream_info->acquired_focus); - /* create virtual stream for ringtone-voip */ - if ((ret = _create_virtual_stream(g_voip_stream_info, &g_voip_vstream_h))) { - ret = MM_ERROR_SOUND_INTERNAL; - goto ERROR_CASE; + /* create and start virtual stream for ringtone-voip */ + if (!g_voip_ringtone_vstream_h) { + if ((ret = _make_progress_virtual_stream(g_voip_ringtone_stream_info, &g_voip_ringtone_vstream_h))) { + ret = MM_ERROR_SOUND_INTERNAL; + goto ERROR_CASE; + } } - if ((ret = _start_virtual_stream(g_voip_vstream_h))) - goto ERROR_CASE; - } else { /* _SESSION_MODE_VOICE_WITH_BUILTIN_RECEIVER: Built-in RCV and Built-in MIC * _SESSION_MODE_VOICE_WITH_BUILTIN_SPEAKER : Built-in SPK and Built-in MIC @@ -1437,31 +1438,32 @@ int _set_session_mode(_session_mode_e mode) goto ERROR_CASE_NO_DESTROY; } - if (g_cached_session_mode == _SESSION_MODE_RINGTONE) { - /* stop vstream and destroy vstream */ - _stop_virtual_stream(g_voip_vstream_h); - _destroy_virtual_stream(g_voip_vstream_h); - g_voip_vstream_h = NULL; - /* destroy stream info */ - _destroy_pa_connection_and_unregister_focus(g_voip_stream_info); - SM_SAFE_FREE(g_voip_stream_info); + if (g_voip_ringtone_vstream_h) { + _stop_progress_virtual_stream(g_voip_ringtone_vstream_h); + g_voip_ringtone_vstream_h = NULL; } - /* create stream info and acquire focus for voip stream */ - if (g_cached_session_mode == -1 || g_cached_session_mode == _SESSION_MODE_RINGTONE) { + + if (!g_voip_stream_info) { + g_voip_stream_info = malloc(sizeof(sound_stream_info_s)); if (!g_voip_stream_info) { - g_voip_stream_info = malloc(sizeof(sound_stream_info_s)); - if (!g_voip_stream_info) { - LOGE("failed to malloc for g_voip_stream_info"); - goto ERROR_CASE; - } - memset(g_voip_stream_info, 0, sizeof(sound_stream_info_s)); - LOGI("g_voip_stream_info(%p) is newly created", g_voip_stream_info); + LOGE("failed to malloc for g_voip_stream_info"); + goto ERROR_CASE; } + memset(g_voip_stream_info, 0, sizeof(sound_stream_info_s)); + LOGI("g_voip_stream_info(%p) is newly created", g_voip_stream_info); g_voip_stream_info->stream_type = "voip"; if ((ret = _make_pa_connection_and_register_focus(g_voip_stream_info, true, _voip_focus_state_change_callback, NULL))) { SM_SAFE_FREE(g_voip_stream_info); goto ERROR_CASE; } + + if ((ret = mm_sound_acquire_focus(g_voip_stream_info->index, FOCUS_FOR_BOTH, EXT_INFO_VOIP_SESSION))) { + if (ret != MM_ERROR_SOUND_INVALID_STATE) + goto ERROR_CASE; + LOGI("already acquired, skip it"); + ret = MM_ERROR_NONE; + } + if (proper_device) { if ((ret = _add_device_for_stream_routing(g_voip_stream_info, proper_device))) goto ERROR_CASE; @@ -1474,21 +1476,17 @@ int _set_session_mode(_session_mode_e mode) if ((ret = _apply_stream_routing(g_voip_stream_info))) goto ERROR_CASE; - /* acquire focus */ - if ((ret = mm_sound_acquire_focus(g_voip_stream_info->index, FOCUS_FOR_BOTH, "for voip session"))) - goto ERROR_CASE; - g_voip_stream_info->acquired_focus |= FOCUS_FOR_BOTH; _update_focus_status(g_voip_stream_info->index, (unsigned int)g_voip_stream_info->acquired_focus); - /* create virtual stream for voip */ - if ((ret = _create_virtual_stream(g_voip_stream_info, &g_voip_vstream_h))) - goto ERROR_CASE; - - if ((ret = _start_virtual_stream(g_voip_vstream_h))) - goto ERROR_CASE; - } else { + if ((ret = mm_sound_acquire_focus(g_voip_stream_info->index, FOCUS_FOR_BOTH, EXT_INFO_VOIP_SESSION))) { + if (ret != MM_ERROR_SOUND_INVALID_STATE) + goto ERROR_CASE_NO_DESTROY; + LOGI("already acquired, skip it"); + ret = MM_ERROR_NONE; + } + if (prev_device) { if ((ret = _remove_device_for_stream_routing(g_voip_stream_info, prev_device))) goto ERROR_CASE_NO_DESTROY; @@ -1508,10 +1506,16 @@ int _set_session_mode(_session_mode_e mode) if ((ret = _apply_stream_routing(g_voip_stream_info))) goto ERROR_CASE_NO_DESTROY; } + + if (!g_voip_vstream_h) { + if ((ret = _make_progress_virtual_stream(g_voip_stream_info, &g_voip_vstream_h))) { + ret = MM_ERROR_SOUND_INTERNAL; + goto ERROR_CASE; + } + } } g_cached_session_mode = mode; - g_cached_voip_device_id = -1; - g_cached_voip_device_id2 = -1; + if (proper_device) mm_sound_get_device_id(proper_device, &g_cached_voip_device_id); if (proper_device2) @@ -1522,15 +1526,21 @@ int _set_session_mode(_session_mode_e mode) return ret; ERROR_CASE: if (g_voip_vstream_h) { - /* destroy virtual stream handle */ _destroy_virtual_stream(g_voip_vstream_h); g_voip_vstream_h = NULL; } + if (g_voip_ringtone_vstream_h) { + _destroy_virtual_stream(g_voip_ringtone_vstream_h); + g_voip_ringtone_vstream_h = NULL; + } if (g_voip_stream_info) { - /* destroy stream info */ _destroy_pa_connection_and_unregister_focus(g_voip_stream_info); SM_SAFE_FREE(g_voip_stream_info); } + if (g_voip_ringtone_stream_info) { + _destroy_pa_connection_and_unregister_focus(g_voip_ringtone_stream_info); + SM_SAFE_FREE(g_voip_ringtone_stream_info); + } ERROR_CASE_NO_DESTROY: if (device_list) mm_sound_free_device_list(device_list); @@ -2098,3 +2108,32 @@ int _stop_virtual_stream(virtual_sound_stream_info_s *virtual_stream) return ret; } + +int _make_progress_virtual_stream(sound_stream_info_s *stream_info, virtual_sound_stream_info_s **virtual_stream) +{ + int ret = MM_ERROR_NONE; + + SM_INSTANCE_CHECK_FOR_PRIV(stream_info); + SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream); + + if ((ret = _create_virtual_stream(stream_info, virtual_stream))) + LOGE("failed to _create_virtual_stream(), ret(0x%x)", ret); + else if ((ret = _start_virtual_stream(*virtual_stream))) + LOGE("failed to _start_virtual_stream(), ret(0x%x)", ret); + + return ret; +} + +int _stop_progress_virtual_stream(virtual_sound_stream_info_s *virtual_stream) +{ + int ret = MM_ERROR_NONE; + + SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream); + + if ((ret = _stop_virtual_stream(virtual_stream))) + LOGE("failed to _stop_virtual_stream(), ret(0x%x)", ret); + else if ((ret = _destroy_virtual_stream(virtual_stream))) + LOGE("failed to _destroy_virtual_stream(), ret(0x%x)", ret); + + return ret; +}