Add null check when destroy sound manager vstream
[platform/core/multimedia/libmm-radio.git] / src / mm_radio_priv_hal.c
index 109e6dc..ac1cd92 100644 (file)
@@ -34,7 +34,6 @@
 #include <errno.h>
 
 #include <mm_error.h>
-#include <mm_debug.h>
 #include <mm_message.h>
 #include <mm_sound.h>
 
@@ -124,18 +123,24 @@ void _mmradio_seek_cancel(mm_radio_t *radio);
 static void __mmradio_seek_thread(mm_radio_t *radio);
 static void __mmradio_scan_thread(mm_radio_t *radio);
 static bool __is_tunable_frequency(mm_radio_t *radio, int freq);
-
-#ifdef TIZEN_FEATURE_SOUND_FOCUS
-static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
-       mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
-       const char *additional_info, void *user_data);
-static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
-       mm_sound_focus_state_e focus_state, const char *reason_for_change,
-       const char *additional_info, void *user_data);
-#endif
+static int __mmradio_create_threads(mm_radio_t *radio);
+static void __mmradio_destroy_threads(mm_radio_t *radio);
+static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
+static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
 
 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data);
-static int __mmradio_set_total_volume(mm_radio_t *radio);
+static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level);
+static int __resource_release_cb(mm_resource_manager_h rm,
+       mm_resource_manager_res_h res, void *user_data);
+static void __mmradio_msg_thread(mm_radio_t *radio);
+static void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data);
+
+typedef void (*thread_function)(mm_radio_t *);
+thread_function __mmradio_thread_function[] = {
+       &__mmradio_msg_thread,
+       &__mmradio_seek_thread,
+       &__mmradio_scan_thread
+};
 
 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
 {
@@ -169,7 +174,7 @@ int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool upda
                }
        }
 
-       MMRADIO_LOG_DEBUG("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz\n",
+       MMRADIO_LOG_INFO("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz",
                radio->region_setting.country, radio->region_setting.deemphasis,
                radio->region_setting.band_min, radio->region_setting.band_max);
 
@@ -189,49 +194,54 @@ int _mmradio_create_radio(mm_radio_t *radio)
 
        /* set default value */
        radio->freq = DEFAULT_FREQ;
-#ifdef TIZEN_FEATURE_SOUND_FOCUS
-       memset(&radio->sound_focus, 0, sizeof(mm_radio_sound_focus));
-#endif
        memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
        radio->local_volume = 1.0;
-
-       /* create command lock */
-       ret = pthread_mutex_init(&radio->cmd_lock, NULL);
-       if (ret) {
-               MMRADIO_LOG_ERROR("mutex creation failed\n");
-               return MM_ERROR_RADIO_INTERNAL;
+       radio->vstream = NULL;
+       radio->stream_info = NULL;
+
+       /* create msg queue for msg thread */
+       radio->msg_queue = g_async_queue_new();
+       if (!radio->msg_queue) {
+               MMRADIO_LOG_ERROR("failed to get msg g_async_queue_new");
+               return  MM_ERROR_RADIO_INTERNAL;
        }
 
-       ret = pthread_mutex_init(&radio->volume_lock, NULL);
+       /* create mutex and thread */
+       ret = __mmradio_create_threads(radio);
        if (ret) {
-               MMRADIO_LOG_ERROR("volume mutex creation failed\n");
-               return MM_ERROR_RADIO_INTERNAL;
+               MMRADIO_LOG_ERROR("failed to create threads");
+               goto ERROR_THREAD;
        }
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
 
-#ifdef TIZEN_FEATURE_SOUND_FOCUS
-       ret = mmradio_sound_focus_register(&radio->sound_focus,
-               (mm_sound_focus_changed_cb)__mmradio_sound_focus_cb,
-               (mm_sound_focus_changed_watch_cb)__mmradio_sound_focus_watch_cb,
-               (void *)radio);
-
+       /* initialize resource manager */
+       ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
+                       __resource_release_cb, radio, &radio->resource_manager);
        if (ret) {
-               /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
-               MMRADIO_LOG_ERROR("mmradio_audio_focus_register is failed\n");
-               return MM_ERROR_RADIO_INTERNAL;
+               MMRADIO_LOG_ERROR("failed to create resource manager");
+               ret = MM_ERROR_RADIO_INTERNAL;
+               goto ERROR_RESOURCE;
        }
-#endif
 
        ret = radio_hal_interface_init(&(radio->hal_inf));
        if (ret) {
-               MMRADIO_LOG_ERROR("mmradio hal interface init failed\n");
-               return ret;
+               MMRADIO_LOG_ERROR("failed to init mmradio hal interface");
+               goto ERROR_HAL_INIT;
        }
 
        MMRADIO_LOG_FLEAVE();
 
        return MM_ERROR_NONE;
+
+ERROR_HAL_INIT:
+       mm_resource_manager_destroy(radio->resource_manager);
+ERROR_RESOURCE:
+       __mmradio_destroy_threads(radio);
+ERROR_THREAD:
+       if (radio->msg_queue)
+               g_async_queue_unref(radio->msg_queue);
+       return ret;
 }
 
 int _mmradio_realize(mm_radio_t *radio)
@@ -247,12 +257,6 @@ int _mmradio_realize(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
 
-       ret = pthread_mutex_init(&radio->seek_cancel_mutex, NULL);
-       if (ret < 0) {
-               MMRADIO_LOG_DEBUG("Mutex creation failed %d", ret);
-               return MM_ERROR_RADIO_INTERNAL;
-       }
-
        if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
                /* not initialized      yet. set it with default region */
                region = RADIO_DEFAULT_REGION;
@@ -267,7 +271,7 @@ int _mmradio_realize(mm_radio_t *radio)
 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
        ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info);
        if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("sound_manager_create_stream_information_internal error");
+               MMRADIO_LOG_ERROR("failed to create stream information");
                MMRADIO_LOG_FLEAVE();
                return ret;
        }
@@ -281,7 +285,7 @@ int _mmradio_realize(mm_radio_t *radio)
 
        ret = sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max);
        if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_WARNING("sound_manager_get_max_volume error");
+               MMRADIO_LOG_WARNING("failed to get max volume");
                radio->max_media_volume = DEFAULT_MAX_MEDIA_VOLUME;
        } else {
                radio->max_media_volume = max;
@@ -290,7 +294,7 @@ int _mmradio_realize(mm_radio_t *radio)
        ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
 
        if (ret != MM_ERROR_NONE)
-               MMRADIO_LOG_WARNING("failed to get MEDIA_VOLUME");
+               MMRADIO_LOG_WARNING("failed to get media volume");
 
        MMRADIO_VOLUME_LOCK(radio);
        radio->media_volume = volume;
@@ -298,7 +302,7 @@ int _mmradio_realize(mm_radio_t *radio)
 
        ret = mm_sound_add_volume_changed_callback(__mmradio_volume_changed_cb, (void *)radio, &radio->volume_subs_id);
        if (ret != MM_ERROR_NONE)
-               MMRADIO_LOG_WARNING("mm_sound_add_volume_changed_callback error");
+               MMRADIO_LOG_WARNING("failed to register volume changed callback");
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
 
@@ -316,20 +320,26 @@ int _mmradio_unrealize(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
 
+       ret = mm_sound_remove_volume_changed_callback(radio->volume_subs_id);
+       if (ret != MM_ERROR_NONE)
+               MMRADIO_LOG_WARNING("mm_sound_remove_volume_changed_callback error");
+
        /*Finish if there are scans*/
        _mmradio_stop_scan(radio);
 
        /*Stop radio if started*/
        _mmradio_stop(radio);
 
-       /* close radio device here !!!! */
-       radio_hal_close(radio->hal_inf);
-       radio_hal_unprepare(radio->hal_inf);
 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
-       sound_manager_destroy_virtual_stream(radio->vstream);
-       sound_manager_destroy_stream_information(radio->stream_info);
+       if (radio->vstream) {
+               sound_manager_destroy_virtual_stream(radio->vstream);
+               radio->vstream = NULL;
+       }
+       if (radio->stream_info) {
+               sound_manager_destroy_stream_information(radio->stream_info);
+               radio->stream_info = NULL;
+       }
 #endif
-       pthread_mutex_destroy(&radio->seek_cancel_mutex);
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
 
@@ -348,18 +358,24 @@ int _mmradio_destroy(mm_radio_t *radio)
 
        _mmradio_unrealize(radio);
 
+       /* destroy mutex and thread */
+       __mmradio_destroy_threads(radio);
+
+       if (radio->msg_queue)
+               g_async_queue_unref(radio->msg_queue);
+
        ret = radio_hal_interface_deinit(radio->hal_inf);
        if (ret) {
-               MMRADIO_LOG_ERROR("mmradio hal interface deinit failed\n");
+               MMRADIO_LOG_ERROR("failed to deinitialize radio hal interface");
                return ret;
        }
-#ifdef TIZEN_FEATURE_SOUND_FOCUS
-       ret = mmradio_sound_focus_deregister(&radio->sound_focus);
+
+       ret = mm_resource_manager_destroy(radio->resource_manager);
        if (ret) {
-               MMRADIO_LOG_ERROR("failed to deregister sound focus\n");
+               MMRADIO_LOG_ERROR("failed to destroy resource manager");
                return MM_ERROR_RADIO_INTERNAL;
        }
-#endif
+
        MMRADIO_LOG_FLEAVE();
 
        return MM_ERROR_NONE;
@@ -375,13 +391,13 @@ int _mmradio_set_frequency(mm_radio_t *radio, int freq)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
 
-       MMRADIO_LOG_DEBUG("Setting %d frequency\n", freq);
+       MMRADIO_LOG_INFO("Setting %d frequency", freq);
 
        radio->freq = freq;
 
        ret = radio_hal_set_frequency(radio->hal_inf, freq);
        if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("radio_hal_set_frequency error");
+               MMRADIO_LOG_ERROR("failed to set radio hal frequency");
                MMRADIO_LOG_FLEAVE();
                return ret;
        }
@@ -401,16 +417,17 @@ int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
 
-       return_val_if_fail(pFreq, MM_ERROR_INVALID_ARGUMENT);
+       MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
 
        ret = radio_hal_get_frequency(radio->hal_inf, &freq);
        if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("radio_hal_get_frequency error");
+               MMRADIO_LOG_ERROR("failed to get radio hal frequency");
                *pFreq = 0;
                return ret;
        }
 
        /* update freq in handle */
+       MMRADIO_LOG_INFO("Updating %d frequency", freq);
        radio->freq = freq;
 
        *pFreq = (int)radio->freq;
@@ -432,12 +449,13 @@ int _mmradio_mute(mm_radio_t *radio)
        if (ret == MM_ERROR_NOT_SUPPORT_API) {
                MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
        } else if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("radio_hal_mute error");
+               MMRADIO_LOG_ERROR("failed to set radio hal mute");
                MMRADIO_LOG_FLEAVE();
                return ret;
        }
 
-       radio->is_muted = TRUE;
+       radio->is_muted = true;
+       MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
        MMRADIO_LOG_FLEAVE();
 
        return ret;
@@ -455,13 +473,13 @@ int _mmradio_unmute(mm_radio_t *radio)
        if (ret == MM_ERROR_NOT_SUPPORT_API) {
                MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
        } else if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("radio_hal_unmute error");
+               MMRADIO_LOG_ERROR("failed to set radio hal unmute");
                MMRADIO_LOG_FLEAVE();
                return ret;
        }
 
-       radio->is_muted = FALSE;
-
+       radio->is_muted = false;
+       MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
        MMRADIO_LOG_FLEAVE();
 
        return ret;
@@ -476,7 +494,7 @@ int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback,
        radio->msg_cb = callback;
        radio->msg_cb_param = user_param;
 
-       MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x\n", callback, user_param);
+       MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -490,7 +508,7 @@ int _mmradio_get_state(mm_radio_t *radio, int *pState)
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
-       return_val_if_fail(pState, MM_ERROR_INVALID_ARGUMENT);
+       MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
 
        state = __mmradio_get_state(radio);
 
@@ -511,24 +529,32 @@ int _mmradio_start(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
 
-       MMRADIO_LOG_DEBUG("now tune to frequency : %d\n", radio->freq);
+       MMRADIO_LOG_INFO("now tune to frequency : %d", radio->freq);
+
+       if (!radio->is_ready) {
+               ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
+                       MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
+                       MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
+               if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+                       MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
+                       return MM_ERROR_RADIO_INTERNAL;
+               }
 
-#ifdef TIZEN_FEATURE_SOUND_FOCUS
-       if (radio->sound_focus.handle > 0) {
-               ret = mmradio_acquire_sound_focus(&radio->sound_focus);
-               if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("failed to set sound focus");
+               radio->interrupted_by_resource_conflict = FALSE;
+               ret = mm_resource_manager_commit(radio->resource_manager);
+               if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+                       MMRADIO_LOG_ERROR("failed to commit resource manager");
+                       mm_resource_manager_mark_for_release(radio->resource_manager,
+                               radio->radio_resource);
+                       radio->radio_resource = NULL;
                        return ret;
                }
-       }
-#endif
 
-       if (!radio->is_ready) {
                ret = radio_hal_prepare(radio->hal_inf);
                if (ret == MM_ERROR_NOT_SUPPORT_API) {
                        MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
                } else if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("radio_hal_prepare_device error");
+                       MMRADIO_LOG_ERROR("failed to prepare radio hal");
                        goto error2;
                }
 
@@ -536,27 +562,21 @@ int _mmradio_start(mm_radio_t *radio)
                if (ret == MM_ERROR_NOT_SUPPORT_API) {
                        MMRADIO_LOG_WARNING("radio_hal_open is not supported");
                } else if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("radio_hal_init error");
+                       MMRADIO_LOG_ERROR("failed to open radio hal");
                        goto error1;
                }
-               radio->is_ready = TRUE;
+               radio->is_ready = true;
        } else {
                MMRADIO_LOG_DEBUG("radio prepared and opened");
        }
 
        ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
        if (ret != MM_ERROR_NONE)
-               MMRADIO_LOG_WARNING("failed to get MEDIA_VOLUME");
-
-       MMRADIO_VOLUME_LOCK(radio);
-       radio->media_volume = volume;
-       MMRADIO_VOLUME_UNLOCK(radio);
+               MMRADIO_LOG_WARNING("failed to get media volume");
 
-       ret = __mmradio_set_total_volume(radio);
-       if (ret == MM_ERROR_NOT_SUPPORT_API) {
-               MMRADIO_LOG_WARNING("radio_hal_set_volume is not supported");
-       } else if (ret) {
-               MMRADIO_LOG_ERROR("failed to radio_hal_set_volume\n");
+       ret = __mmradio_set_media_volume(radio, volume);
+       if (ret != MM_ERROR_NONE) {
+               MMRADIO_LOG_ERROR("failed to set media volume");
                goto error1;
        }
 
@@ -564,22 +584,22 @@ int _mmradio_start(mm_radio_t *radio)
        if (ret == MM_ERROR_NOT_SUPPORT_API) {
                MMRADIO_LOG_WARNING("radio_hal_start is not supported");
        } else if (ret) {
-               MMRADIO_LOG_ERROR("failed to radio_hal_start\n");
+               MMRADIO_LOG_ERROR("failed to start radio hal");
                goto error1;
        }
 
        /* set stored frequency */
        ret = radio_hal_set_frequency(radio->hal_inf, radio->freq);
        if (ret) {
-               MMRADIO_LOG_ERROR("failed to radio_hal_set_frequency\n");
+               MMRADIO_LOG_ERROR("failed to set radio hal frequency");
                goto error1;
        }
 
 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
        ret = sound_manager_start_virtual_stream(radio->vstream);
        if (ret) {
-               MMRADIO_LOG_ERROR("failed to sound_manager_start_virtual_stream\n");
-               goto error;
+               MMRADIO_LOG_ERROR("failed to start sound manager virtual stream");
+               goto error1;
        }
 #endif
 
@@ -589,15 +609,11 @@ int _mmradio_start(mm_radio_t *radio)
 
        return MM_ERROR_NONE;
 
-#ifdef TIZEN_FEATURE_SOUND_VSTREAM
-error:
-       sound_manager_stop_virtual_stream(radio->vstream);
-#endif
 error1:
        radio_hal_close(radio->hal_inf);
 error2:
        radio_hal_unprepare(radio->hal_inf);
-       radio->is_ready = FALSE;
+       radio->is_ready = false;
        return ret;
 }
 
@@ -610,7 +626,6 @@ int _mmradio_stop(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
 
-       radio->seek_unmute = FALSE;
        /*cancel if any seek*/
        _mmradio_seek_cancel(radio);
 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
@@ -625,38 +640,46 @@ int _mmradio_stop(mm_radio_t *radio)
        if (ret == MM_ERROR_NOT_SUPPORT_API) {
                MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
        } else if (ret) {
-               MMRADIO_LOG_ERROR("failed to radio_hal_stop\n");
+               MMRADIO_LOG_ERROR("failed to stop radio hal");
                return ret;
        }
 
-       /* close radio device here !!!! */
-       ret = radio_hal_close(radio->hal_inf);
-       if (ret == MM_ERROR_NOT_SUPPORT_API) {
-               MMRADIO_LOG_WARNING("radio_hal_close is not supported");
-       } else if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("radio_hal_close_device error");
-               return ret;
-       }
+       if (radio->is_ready) {
+               /* close radio device here !!!! */
+               ret = radio_hal_close(radio->hal_inf);
+               if (ret == MM_ERROR_NOT_SUPPORT_API) {
+                       MMRADIO_LOG_WARNING("radio_hal_close is not supported");
+               } else if (ret != MM_ERROR_NONE) {
+                       MMRADIO_LOG_ERROR("failed to close radio hal");
+                       return ret;
+               }
 
-       ret = radio_hal_unprepare(radio->hal_inf);
-       if (ret == MM_ERROR_NOT_SUPPORT_API) {
-               MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
-       } else if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("radio_hal_close_device error");
-               return ret;
-       }
+               ret = radio_hal_unprepare(radio->hal_inf);
+               if (ret == MM_ERROR_NOT_SUPPORT_API) {
+                       MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
+               } else if (ret != MM_ERROR_NONE) {
+                       MMRADIO_LOG_ERROR("failed to unprepare radio hal");
+                       return ret;
+               }
 
-       radio->is_ready = FALSE;
+               if (!radio->interrupted_by_resource_conflict && /* is being released */
+                               radio->radio_resource != NULL) {
+                       ret = mm_resource_manager_mark_for_release(radio->resource_manager,
+                                       radio->radio_resource);
+                       radio->radio_resource = NULL;
+                       if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+                               MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
+                               return ret;
+                       }
 
-#ifdef TIZEN_FEATURE_SOUND_FOCUS
-       if (radio->sound_focus.handle > 0) {
-               ret = mmradio_release_sound_focus(&radio->sound_focus);
-               if (ret) {
-                       MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed\n");
-                       return ret;
+                       ret = mm_resource_manager_commit(radio->resource_manager);
+                       if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
+                               MMRADIO_LOG_ERROR("resource manager commit fail");
                }
+
+               radio->is_ready = false;
        }
-#endif
+
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
 
        MMRADIO_LOG_FLEAVE();
@@ -667,53 +690,40 @@ int _mmradio_stop(mm_radio_t *radio)
 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
 {
        int ret = MM_ERROR_NONE;
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
 
-       if (radio->is_seeking) {
+       p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
+       MMRADIO_CHECK_ARG(p_thread);
+
+       if (p_thread->is_running) {
                MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
                return MM_ERROR_RADIO_INTERNAL;
        }
 
-       radio->seek_unmute = FALSE;
-       radio->is_seeking = TRUE;
-       radio->seek_cancel = FALSE;
+       radio->seek_unmute = false;
 
        if (!radio->is_muted) {
                ret = radio_hal_mute(radio->hal_inf);
                if (ret == MM_ERROR_NOT_SUPPORT_API) {
                        MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
                } else if (ret) {
-                       MMRADIO_LOG_ERROR("failed to radio_hal_mute\n");
+                       MMRADIO_LOG_ERROR("failed to set radio hal mute");
                        return ret;
                }
-               radio->seek_unmute = TRUE;
+               radio->seek_unmute = true;
        }
 
-       MMRADIO_LOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d\n", direction);
+       MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
        radio->seek_direction = direction;
+       p_thread->is_running = true;
+       p_thread->stop = false;
 
-       ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio);
-
-       if (ret) {
-               MMRADIO_LOG_DEBUG("failed create thread\n");
-               radio->is_seeking = FALSE;
-               radio->seek_cancel = TRUE;
-               if (radio->seek_unmute) {
-                       ret = radio_hal_mute(radio->hal_inf);
-                       if (ret == MM_ERROR_NOT_SUPPORT_API) {
-                               MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
-                       } else if (ret) {
-                               MMRADIO_LOG_ERROR("failed to radio_hal_mute\n");
-                               radio->seek_unmute = FALSE;
-                               return ret;
-                       }
-               }
-               return MM_ERROR_RADIO_INTERNAL;
-       }
+       MMRADIO_THREAD_SIGNAL(p_thread);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -722,54 +732,55 @@ int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
 
 void _mmradio_seek_cancel(mm_radio_t *radio)
 {
-       int ret = MM_ERROR_NONE;
-       char str_error[READ_MAX_BUFFER_SIZE];
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       /*cancel any outstanding seek request*/
-       radio->seek_cancel = TRUE;
-       if (radio->seek_thread) {
-               ret = pthread_mutex_trylock(&radio->seek_cancel_mutex);
-               MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret);
-               if (ret == EBUSY) { /* it was already locked by other */
-                       MMRADIO_LOG_DEBUG("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
-               } else if (ret == 0) {
-                       MMRADIO_LOG_DEBUG("trylock is successful. unlock now");
-                       pthread_mutex_unlock(&radio->seek_cancel_mutex);
-               } else {
-                       MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret);
-               }
-               MMRADIO_LOG_DEBUG("pthread_join seek_thread");
-               pthread_join(radio->seek_thread, NULL);
-               MMRADIO_LOG_DEBUG("done");
-               radio->is_seeking = FALSE;
-               radio->seek_thread = 0;
-       }
+       /* cancel any outstanding seek request */
+       radio->thread[MM_RADIO_THREAD_SEEK].stop = true;
+
        MMRADIO_LOG_FLEAVE();
 }
 
-
 int _mmradio_start_scan(mm_radio_t *radio)
 {
        int ret = MM_ERROR_NONE;
+       MMRadioThread_t *p_thread = NULL;;
 
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
 
-       int scan_tr_id = 0;
+       p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
+       MMRADIO_CHECK_ARG(p_thread);
 
-       radio->stop_scan = false;
+       p_thread->stop = false;
 
        if (!radio->is_ready) {
+               ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
+                       MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
+                       MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
+               if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+                       MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
+                       return MM_ERROR_RADIO_INTERNAL;
+               }
+
+               radio->interrupted_by_resource_conflict = FALSE;
+               ret = mm_resource_manager_commit(radio->resource_manager);
+               if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+                       MMRADIO_LOG_ERROR("failed to commit resource manager");
+                       mm_resource_manager_mark_for_release(radio->resource_manager,
+                               radio->radio_resource);
+                       radio->radio_resource = NULL;
+                       return ret;
+               }
+
                ret = radio_hal_prepare(radio->hal_inf);
                if (ret == MM_ERROR_NOT_SUPPORT_API) {
                        MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
                } else if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("radio_hal_prepare_device error");
+                       MMRADIO_LOG_ERROR("failed to prepare radio hal");
                        return ret;
                }
 
@@ -777,21 +788,18 @@ int _mmradio_start_scan(mm_radio_t *radio)
                if (ret == MM_ERROR_NOT_SUPPORT_API) {
                        MMRADIO_LOG_WARNING("radio_hal_open is not supported");
                } else if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("radio_hal_init error");
+                       MMRADIO_LOG_ERROR("failed to open radio hal");
                        MMRADIO_LOG_FLEAVE();
                        return ret;
                }
-               radio->is_ready = TRUE;
+               radio->is_ready = true;
        } else {
                MMRADIO_LOG_DEBUG("radio prepared and opened");
        }
 
-       scan_tr_id = pthread_create(&radio->scan_thread, NULL, (void *)__mmradio_scan_thread, (void *)radio);
+       p_thread->is_running = true;
 
-       if (scan_tr_id != 0) {
-               MMRADIO_LOG_DEBUG("failed to create thread : scan\n");
-               return MM_ERROR_RADIO_NOT_INITIALIZED;
-       }
+       MMRADIO_THREAD_SIGNAL(p_thread);
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
@@ -802,31 +810,12 @@ int _mmradio_start_scan(mm_radio_t *radio)
 
 int _mmradio_stop_scan(mm_radio_t *radio)
 {
-       int ret = 0;
-       char str_error[READ_MAX_BUFFER_SIZE];
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
 
-       radio->stop_scan = true;
-
-       if (radio->scan_thread > 0) {
-               /* make sure all the search is stopped else we'll wait till search finish which is not ideal*/
-               ret = pthread_mutex_trylock(&radio->seek_cancel_mutex);
-               MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret);
-               if (ret == EBUSY) { /* it was already locked by other */
-                       MMRADIO_LOG_DEBUG("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
-               } else if (ret == 0) {
-                       MMRADIO_LOG_DEBUG("trylock is successful. unlock now");
-                       pthread_mutex_unlock(&radio->seek_cancel_mutex);
-               } else {
-                       MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret);
-               }
-               MMRADIO_LOG_DEBUG("pthread_join scan_thread");
-               pthread_join(radio->scan_thread, NULL);
-               radio->scan_thread = 0;
-       }
+       radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
 
        MMRADIO_LOG_FLEAVE();
 
@@ -836,18 +825,18 @@ int _mmradio_stop_scan(mm_radio_t *radio)
 int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value)
 {
        int ret = MM_ERROR_NONE;
-       uint32_t strength = 0;
+       int32_t strength = 0;
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE(radio);
 
-       return_val_if_fail(value, MM_ERROR_INVALID_ARGUMENT);
+       MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
 
        /* just return stored frequency if radio device is not ready */
        ret = radio_hal_get_signal_strength(radio->hal_inf, &strength);
        if (ret == MM_ERROR_NOT_SUPPORT_API) {
                MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
        } else if (ret != MM_ERROR_NONE) {
-               debug_error("radio_hal_get_signal_strength error\n");
+               MMRADIO_LOG_ERROR("failed to get radio hal signal strength");
                *value = 0;
                MMRADIO_LOG_FLEAVE();
                return ret;
@@ -862,137 +851,182 @@ void __mmradio_scan_thread(mm_radio_t *radio)
        int ret = MM_ERROR_NONE;
        int prev_freq = 0;
 
+       MMRadioThread_t *p_thread = NULL;
+
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       ret = radio_hal_mute(radio->hal_inf);
+       p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
 
-       if (ret == MM_ERROR_NOT_SUPPORT_API) {
-               MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
-       } else if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("radio_hal_mute error");
-               goto FINISHED;
-       }
-       ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
-
-       if (ret != MM_ERROR_NONE)
-               goto FINISHED;
-
-       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
-       MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
-       while (!radio->stop_scan) {
-               uint32_t freq = 0;
-               MMMessageParamType param = { 0, };
+       MMRADIO_THREAD_LOCK(p_thread);
 
-               MMRADIO_LOG_DEBUG("scanning....\n");
+       while (!p_thread->thread_exit) {
+               MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
+               MMRADIO_THREAD_WAIT(p_thread);
 
-               pthread_mutex_lock(&radio->seek_cancel_mutex);
+               if (p_thread->thread_exit) {
+                       MMRADIO_LOG_DEBUG("exiting scan thread");
+                       goto EXIT;
+               }
 
-               if (radio->stop_scan) {
-                       MMRADIO_LOG_DEBUG("scan was canceled");
-                       pthread_mutex_unlock(&radio->seek_cancel_mutex);
-                       goto FINISHED;
+               if (radio->old_state == MM_RADIO_STATE_PLAYING) {
+                       ret = radio_hal_mute(radio->hal_inf);
+                       if (ret == MM_ERROR_NOT_SUPPORT_API) {
+                               MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
+                       } else if (ret != MM_ERROR_NONE) {
+                               MMRADIO_LOG_ERROR("faied to set radio hal mute");
+                               goto FINISHED;
+                       }
                }
 
-               ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
+               ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
+               if (ret != MM_ERROR_NONE)
+                       goto FINISHED;
 
-               pthread_mutex_unlock(&radio->seek_cancel_mutex);
+               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
+               MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
-               if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("radio scanning error");
-                       break;
-               }
+               prev_freq = 0;
+               while (!p_thread->stop) {
+                       uint32_t freq = 0;
 
-               /* now we can get new frequency from radio device */
-               if (radio->stop_scan)
-                       break;
+                       MMRADIO_LOG_DEBUG("scanning....");
 
-               ret = radio_hal_get_frequency(radio->hal_inf, &freq);
-               if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("failed to get current frequency\n");
-               } else {
-                       if (freq < prev_freq) {
-                               MMRADIO_LOG_DEBUG("scanning wrapped around. stopping scan\n");
-                               break;
+                       if (p_thread->thread_exit) {
+                               MMRADIO_LOG_DEBUG("exiting scan thread");
+                               goto EXIT;
                        }
 
-                       if (freq == prev_freq)
-                               continue;
-
-                       prev_freq = param.radio_scan.frequency = (int)freq;
-                       MMRADIO_LOG_DEBUG("scanning : new frequency : [%d]\n", param.radio_scan.frequency);
+                       if (p_thread->stop) {
+                               MMRADIO_LOG_INFO("scan was canceled");
+                               goto FINISHED;
+                       }
 
-                       /* drop if max freq is scanned */
-                       if (param.radio_scan.frequency == radio->region_setting.band_max) {
-                               MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan\n", param.radio_scan.frequency);
+                       MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
+                       ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
+                       MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
+                       if (ret != MM_ERROR_NONE) {
+                               MMRADIO_LOG_ERROR("radio scanning error");
                                break;
                        }
 
-                       if (radio->stop_scan) {
-                               /* doesn't need to post */
-                               break;
+                       if (p_thread->thread_exit) {
+                               MMRADIO_LOG_DEBUG("exiting scan thread");
+                               goto EXIT;
                        }
 
-                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
+                       if (p_thread->stop) {
+                               MMRADIO_LOG_INFO("scan was canceled");
+                               goto FINISHED;
+                       }
+
+                       /* now we can get new frequency from radio device */
+                       ret = radio_hal_get_frequency(radio->hal_inf, &freq);
+                       if (ret != MM_ERROR_NONE) {
+                               MMRADIO_LOG_ERROR("failed to get current frequency");
+                       } else {
+                               if (freq <= prev_freq) {
+                                       MMRADIO_LOG_ERROR("frequency is less than previous [%d] -> [%d] we wrapped around, we are finished scanning", prev_freq, freq);
+                                       break;
+                               }
+
+                               prev_freq = (int)freq;
+                               MMRADIO_LOG_INFO("scanning : new frequency : [%d]", prev_freq);
+
+                               /* drop if max freq is scanned */
+                               if (prev_freq >= radio->region_setting.band_max) {
+                                       MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", prev_freq);
+                                       break;
+                               }
+
+                               if (p_thread->stop) {
+                                       /* doesn't need to post */
+                                       break;
+                               }
+
+                               __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
+                       }
                }
-       }
+
 FINISHED:
-       if (radio->old_state == MM_RADIO_STATE_READY) {
-               MMRADIO_LOG_DEBUG("old state is ready");
-       } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
-               MMRADIO_LOG_DEBUG("old state is playing");
-               ret = radio_hal_unmute(radio->hal_inf);
-               if (ret == MM_ERROR_NOT_SUPPORT_API) {
-                       MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
-               } else if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("radio_hal_unmute error");
-                       goto FINISHED_ERR;
-               }
-               ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
-               if (ret == MM_ERROR_NOT_SUPPORT_API) {
-                       MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
-               } else if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("radio_hal_set_frequency error");
-                       goto FINISHED_ERR;
+               if (radio->old_state == MM_RADIO_STATE_READY) {
+                       MMRADIO_LOG_DEBUG("old state is ready");
+               } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
+                       MMRADIO_LOG_DEBUG("old state is playing");
+                       ret = radio_hal_unmute(radio->hal_inf);
+                       if (ret == MM_ERROR_NOT_SUPPORT_API) {
+                               MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
+                       } else if (ret != MM_ERROR_NONE) {
+                               MMRADIO_LOG_ERROR("failed to set radio hal unmute");
+                               goto FINISHED_ERR;
+                       }
+                       ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
+                       if (ret == MM_ERROR_NOT_SUPPORT_API) {
+                               MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
+                       } else if (ret != MM_ERROR_NONE) {
+                               MMRADIO_LOG_ERROR("failed to set radio hal frequency");
+                               goto FINISHED_ERR;
+                       }
                }
-       }
 
 FINISHED_ERR:
+               if (radio->old_state == MM_RADIO_STATE_PLAYING) {
+                       MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
+               } else {
+                       /* close radio device here !!!! */
+                       if (radio->is_ready) {
+                               ret = radio_hal_close(radio->hal_inf);
+                               if (ret == MM_ERROR_NOT_SUPPORT_API)
+                                       MMRADIO_LOG_WARNING("radio_hal_close is not supported");
+                               else if (ret != MM_ERROR_NONE)
+                                       MMRADIO_LOG_ERROR("failed to close radio hal");
+
+                               ret = radio_hal_unprepare(radio->hal_inf);
+                               if (ret == MM_ERROR_NOT_SUPPORT_API)
+                                       MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
+                               else if (ret != MM_ERROR_NONE)
+                                       MMRADIO_LOG_ERROR("failed to unprepare radio hal");
+
+                               if (!radio->interrupted_by_resource_conflict && /* is being released */
+                                               radio->radio_resource != NULL) {
+                                       ret = mm_resource_manager_mark_for_release(radio->resource_manager,
+                                                       radio->radio_resource);
+                                       radio->radio_resource = NULL;
+                                       if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
+                                               MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
+                               }
+
+                               ret = mm_resource_manager_commit(radio->resource_manager);
+                               if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
+                                       MMRADIO_LOG_ERROR("resource manager commit fail");
+                               radio->is_ready = false;
+                       }
+                       MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
+               }
 
-       radio->scan_thread = 0;
-
-       if (radio->old_state == MM_RADIO_STATE_PLAYING) {
-               MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
-       } else {
-               /* close radio device here !!!! */
-               ret = radio_hal_close(radio->hal_inf);
-               if (ret == MM_ERROR_NOT_SUPPORT_API)
-                       MMRADIO_LOG_WARNING("radio_hal_close is not supported");
-               else if (ret != MM_ERROR_NONE)
-                       MMRADIO_LOG_ERROR("radio_hal_close_device error");
-
-               ret = radio_hal_unprepare(radio->hal_inf);
-               if (ret == MM_ERROR_NOT_SUPPORT_API)
-                       MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
-               else if (ret != MM_ERROR_NONE)
-                       MMRADIO_LOG_ERROR("radio_hal_close_device error");
+               if (!p_thread->stop)
+                       __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
+               else
+                       __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
 
-               radio->is_ready = FALSE;
+               p_thread->is_running = false;
 
-               MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
        }
 
-       if (!radio->stop_scan)
-               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
-       else
-               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
+EXIT:
+       p_thread->is_running = false;
+
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
        MMRADIO_LOG_FLEAVE();
 
        pthread_exit(NULL);
 
-       return;
 }
 
 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
@@ -1014,46 +1048,69 @@ void __mmradio_seek_thread(mm_radio_t *radio)
 {
        int ret = MM_ERROR_NONE;
        uint32_t freq = 0;
-       MMMessageParamType param = {0, };
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
+       p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
 
-       MMRADIO_LOG_DEBUG("seeking....\n");
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
-       if (!radio->seek_cancel) {
+       MMRADIO_THREAD_LOCK(p_thread);
 
-               MMRADIO_LOG_DEBUG("try to seek ");
-               pthread_mutex_lock(&radio->seek_cancel_mutex);
-               MMRADIO_LOG_DEBUG("seek start\n");
+       while (!p_thread->thread_exit) {
+               MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.");
+               MMRADIO_THREAD_WAIT(p_thread);
 
-               if (radio->seek_cancel) {
-                       MMRADIO_LOG_DEBUG("seek was canceled so we return failure to application");
-                       pthread_mutex_unlock(&radio->seek_cancel_mutex);
-                       goto SEEK_FAILED;
+               if (p_thread->thread_exit) {
+                       MMRADIO_LOG_DEBUG("exiting seek thread");
+                       goto EXIT;
                }
 
+               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
+               MMRADIO_LOG_DEBUG("seeking....");
+
+               if (p_thread->stop) {
+                       MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
+                       goto SEEK_FAILED;
+               }
+               freq = 0;
+               MMRADIO_LOG_DEBUG("try to seek ");
+               MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
+               MMRADIO_LOG_DEBUG("seek start");
                ret = radio_hal_seek(radio->hal_inf, radio->seek_direction);
-               pthread_mutex_unlock(&radio->seek_cancel_mutex);
+               MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
                if (ret) {
-                       MMRADIO_LOG_ERROR("radio_hal_seek failed\n");
+                       MMRADIO_LOG_ERROR("failed to seek radio hal");
+                       goto SEEK_FAILED;
+               }
+
+               if (p_thread->thread_exit) {
+                       MMRADIO_LOG_DEBUG("exiting seek thread");
+                       goto EXIT;
+               }
+
+               if (p_thread->stop) {
+                       MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
                        goto SEEK_FAILED;
                }
 
                /* now we can get new frequency from radio device */
                ret = radio_hal_get_frequency(radio->hal_inf, &freq);
                if (ret) {
-                       MMRADIO_LOG_ERROR("failed to get current frequency\n");
+                       MMRADIO_LOG_ERROR("failed to get current frequency");
                        goto SEEK_FAILED;
                }
 
-               MMRADIO_LOG_DEBUG("found frequency\n");
+               MMRADIO_LOG_DEBUG("found frequency");
 
                /* if same freq is found, ignore it and search next one. */
                if (freq == radio->prev_seek_freq) {
-                       MMRADIO_LOG_DEBUG("It's same with previous found one. So, trying next one. \n");
+                       MMRADIO_LOG_WARNING("It's same with previous found one. So, trying next one.");
                        goto SEEK_FAILED;
                }
 
@@ -1062,9 +1119,11 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                        /* now tune to new frequency */
                        ret = radio_hal_set_frequency(radio->hal_inf, freq);
                        if (ret) {
-                               MMRADIO_LOG_ERROR("failed to tune to new frequency\n");
+                               MMRADIO_LOG_ERROR("failed to tune to new frequency");
                                goto SEEK_FAILED;
                        }
+                       radio->freq = (int)freq;
+                       MMRADIO_LOG_WARNING("setting frequency : [%d]", radio->freq);
                }
 
                if (radio->seek_unmute) {
@@ -1074,43 +1133,39 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                         */
                        ret = radio_hal_unmute(radio->hal_inf);
                        if (ret) {
-                               MMRADIO_LOG_ERROR("failed to tune to new frequency\n");
+                               MMRADIO_LOG_ERROR("failed to set unmute radio hal");
                                goto SEEK_FAILED;
                        }
-                       radio->seek_unmute = FALSE;
+                       radio->seek_unmute = false;
                }
 
-               param.radio_scan.frequency = radio->prev_seek_freq = (int)freq;
-               MMRADIO_LOG_DEBUG("seeking : new frequency : [%d]\n", param.radio_scan.frequency);
-               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
-       }
-
-       radio->seek_thread = 0;
-       radio->is_seeking = FALSE;
-
-       MMRADIO_LOG_FLEAVE();
-
-       pthread_exit(NULL);
-       return;
+               radio->prev_seek_freq = (int)freq;
+               MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
+               __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
+               p_thread->is_running = false;
+               continue;
 
 SEEK_FAILED:
-
-       if (radio->seek_unmute) {
-               /* now turn on radio
-               * In the case of limit freq, tuner should be unmuted.
-               * Otherwise, sound can't output even though application set new frequency.
-               */
-               ret = radio_hal_unmute(radio->hal_inf);
-               if (ret)
-                       MMRADIO_LOG_ERROR("failed to tune to new frequency\n");
-               radio->seek_unmute = FALSE;
+               if (radio->seek_unmute) {
+                       /* now turn on radio
+                       * In the case of limit freq, tuner should be unmuted.
+                       * Otherwise, sound can't output even though application set new frequency.
+                       */
+                       ret = radio_hal_unmute(radio->hal_inf);
+                       if (ret)
+                               MMRADIO_LOG_ERROR("failed to set unmute radio hal");
+                       radio->seek_unmute = false;
+               }
+               /* freq -1 means it's failed to seek */
+               __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
+               p_thread->is_running = false;
        }
-       /* freq -1 means it's failed to seek */
-       param.radio_scan.frequency = -1;
-       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
-       radio->is_seeking = FALSE;
+
+EXIT:
+       p_thread->is_running = false;
+       MMRADIO_THREAD_UNLOCK(p_thread);
+       MMRADIO_LOG_FLEAVE();
        pthread_exit(NULL);
-       return;
 }
 
 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param)
@@ -1120,11 +1175,11 @@ static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype
        MMRADIO_LOG_FENTER();
 
        if (!radio->msg_cb) {
-               debug_warning("failed to post a message\n");
+               MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
                return false;
        }
 
-       MMRADIO_LOG_DEBUG("address of msg_cb : %p\n", radio->msg_cb);
+       MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
 
        radio->msg_cb(msgtype, param, radio->msg_cb_param);
 
@@ -1143,7 +1198,7 @@ static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
 
        radio_state = __mmradio_get_state(radio);
 
-       MMRADIO_LOG_DEBUG("incomming command : %d  current state : %d\n", command, radio_state);
+       MMRADIO_LOG_INFO("incomming command : %d  current state : %d", command, radio_state);
 
        switch (command) {
        case MMRADIO_COMMAND_CREATE:
@@ -1242,11 +1297,11 @@ static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
                break;
 
        default:
-               MMRADIO_LOG_DEBUG("not handled in FSM. don't care it\n");
+               MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
                break;
        }
 
-       MMRADIO_LOG_DEBUG("status OK\n");
+       MMRADIO_LOG_DEBUG("status OK");
 
        radio->cmd = command;
 
@@ -1254,13 +1309,13 @@ static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
 
        return MM_ERROR_NONE;
 
- INVALID_STATE:
-       debug_warning("invalid state. current : %d  command : %d\n", radio_state, command);
+INVALID_STATE:
+       MMRADIO_LOG_WARNING("invalid state. current : %d  command : %d", radio_state, command);
        MMRADIO_LOG_FLEAVE();
        return MM_ERROR_RADIO_INVALID_STATE;
 
- NO_OP:
-       debug_warning("mm-radio is in the desired state(%d). doing noting\n", radio_state);
+NO_OP:
+       MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
        MMRADIO_LOG_FLEAVE();
        return MM_ERROR_RADIO_NO_OP;
 
@@ -1272,15 +1327,14 @@ static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
        int msg_type = MM_MESSAGE_UNKNOWN;
 
        MMRADIO_LOG_FENTER();
-       MMRADIO_CHECK_INSTANCE(radio);
 
        if (!radio) {
-               debug_warning("calling set_state with invalid radio handle\n");
+               MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
                return false;
        }
 
        if (radio->current_state == new_state && radio->pending_state == 0) {
-               debug_warning("we are in same state\n");
+               MMRADIO_LOG_WARNING("we are in same state");
                return true;
        }
 
@@ -1289,36 +1343,17 @@ static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
        radio->current_state = new_state;
 
        /* fill message param */
+       msg.union_type = MM_MSG_UNION_STATE;
        msg.state.previous = radio->old_state;
        msg.state.current = radio->current_state;
 
-#ifdef TIZEN_FEATURE_SOUND_FOCUS
-       /* post message to application */
-       switch (radio->sound_focus.by_focus_cb) {
-       case MMRADIO_FOCUS_CB_NONE:
-               {
-                       msg_type = MM_MESSAGE_STATE_CHANGED;
-                       MMRADIO_POST_MSG(radio, msg_type, &msg);
-               }
-               break;
-
-       case MMRADIO_FOCUS_CB_POSTMSG:
-               {
-                       msg_type = MM_MESSAGE_STATE_INTERRUPTED;
-                       msg.union_type = MM_MSG_UNION_CODE;
-                       msg.code = radio->sound_focus.event_src;
-                       MMRADIO_POST_MSG(radio, msg_type, &msg);
-               }
-               break;
-
-       case MMRADIO_FOCUS_CB_SKIP_POSTMSG:
-       default:
-               break;
+       if (radio->interrupted_by_resource_conflict) {
+               __mmradio_msg_push(radio, MM_RADIO_MSG_STATE_INTERRUPTED,
+                       MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT);
+       } else {
+               msg_type = MM_MESSAGE_STATE_CHANGED;
+               MMRADIO_POST_MSG(radio, msg_type, &msg);
        }
-#else
-       msg_type = MM_MESSAGE_STATE_CHANGED;
-       MMRADIO_POST_MSG(radio, msg_type, &msg);
-#endif
 
        MMRADIO_LOG_FLEAVE();
 
@@ -1329,255 +1364,413 @@ static int __mmradio_get_state(mm_radio_t *radio)
 {
        MMRADIO_CHECK_INSTANCE(radio);
 
-       MMRADIO_LOG_DEBUG("radio state : current : [%d]   old : [%d]   pending : [%d]\n",
+       MMRADIO_LOG_INFO("radio state : current : [%d]   old : [%d]   pending : [%d]",
                radio->current_state, radio->old_state, radio->pending_state);
 
        return radio->current_state;
 }
 
-#ifdef TIZEN_FEATURE_SOUND_FOCUS
-static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
-       mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
-       const char *additional_info, void *user_data)
+static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
 {
        mm_radio_t *radio = (mm_radio_t *)user_data;
-       enum MMMessageInterruptedCode event_source;
-       int result = MM_ERROR_NONE;
-       int postMsg = false;
+       int ret = MM_ERROR_NONE;
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
+       if (type == VOLUME_TYPE_MEDIA) {
+               MMRADIO_LOG_INFO("Change FM Radio volume to %d", volume);
+               ret = __mmradio_set_media_volume(radio, volume);
+               if (ret != MM_ERROR_NONE)
+                       MMRADIO_LOG_ERROR("failed to set media volume");
+               return;
+       }
+}
 
+int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
+{
        MMRADIO_LOG_FENTER();
-       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
+       MMRADIO_CHECK_INSTANCE(radio);
+       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
 
-       mmradio_get_sound_focus_reason(focus_state, reason_for_change, &event_source, &postMsg);
-       radio->sound_focus.event_src = event_source;
+       MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
 
-       switch (focus_state) {
-       case FOCUS_IS_RELEASED:{
-                       radio->sound_focus.cur_focus_type &= ~focus_type;
-                       radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG;
+       *type = radio->region_setting.country;
 
-                       result = _mmradio_stop(radio);
-                       if (result)
-                               MMRADIO_LOG_ERROR("failed to stop radio\n");
+       MMRADIO_LOG_FLEAVE();
+       return MM_ERROR_NONE;
+}
 
-                       MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type);
-               }
-               break;
+int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
+{
+       MMRADIO_LOG_FENTER();
+       MMRADIO_CHECK_INSTANCE(radio);
+       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
 
-       case FOCUS_IS_ACQUIRED:{
-                       MMMessageParamType msg = { 0, };
-                       msg.union_type = MM_MSG_UNION_CODE;
-                       msg.code = event_source;
+       MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
 
-                       radio->sound_focus.cur_focus_type |= focus_type;
+       *min_freq = radio->region_setting.band_min;
+       *max_freq = radio->region_setting.band_max;
 
-                       if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
-                               MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
+       MMRADIO_LOG_FLEAVE();
+       return MM_ERROR_NONE;
+}
 
-                       radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_NONE;
+int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
+{
+       MMRADIO_LOG_FENTER();
+       MMRADIO_CHECK_INSTANCE(radio);
+       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
 
-                       MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type);
-               }
-               break;
+       MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
 
-       default:
-               MMRADIO_LOG_DEBUG("Unknown focus_state\n");
-               break;
-       }
+       *ch_spacing = radio->region_setting.channel_spacing;
 
        MMRADIO_LOG_FLEAVE();
+       return MM_ERROR_NONE;
 }
 
-static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
-       mm_sound_focus_state_e focus_state, const char *reason_for_change,
-       const char *additional_info, void *user_data)
+int _mmradio_set_volume(mm_radio_t *radio, float volume)
 {
-       mm_radio_t *radio = (mm_radio_t *)user_data;
-       enum MMMessageInterruptedCode event_source;
-       int result = MM_ERROR_NONE;
-       int postMsg = false;
+       int ret = MM_ERROR_NONE;
 
        MMRADIO_LOG_FENTER();
-       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       mmradio_get_sound_focus_reason(focus_state, reason_for_change, &event_source, &postMsg);
-       radio->sound_focus.event_src = event_source;
+       MMRADIO_CHECK_INSTANCE(radio);
+       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
 
-       switch (focus_state) {
-       case FOCUS_IS_ACQUIRED: {
-                       radio->sound_focus.cur_focus_type &= ~focus_type;
-                       radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG;
+       MMRADIO_LOG_INFO("Setting %f volume", volume);
 
-                       result = _mmradio_stop(radio);
-                       if (result)
-                               MMRADIO_LOG_ERROR("failed to stop radio\n");
+       MMRADIO_VOLUME_LOCK(radio);
+       radio->local_volume = volume;
+       MMRADIO_VOLUME_UNLOCK(radio);
 
-                       MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type);
-               }
-               break;
+       ret = radio_hal_set_volume(radio->hal_inf, volume);
+       if (ret != MM_ERROR_NONE)
+               MMRADIO_LOG_ERROR("failed to set radio hal volume");
 
-       case FOCUS_IS_RELEASED: {
-                       MMMessageParamType msg = { 0, };
-                       msg.union_type = MM_MSG_UNION_CODE;
-                       msg.code = event_source;
+       MMRADIO_LOG_FLEAVE();
 
-                       radio->sound_focus.cur_focus_type |= focus_type;
+       return ret;
+}
 
-                       if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
-                               MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
+int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
+{
+       int ret = MM_ERROR_NONE;
+       float volume = 0.0;
+       MMRADIO_LOG_FENTER();
 
-                       radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_NONE;
+       MMRADIO_CHECK_INSTANCE(radio);
+       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
 
-                       MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type);
-               }
-               break;
+       MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
 
-       default:
-               MMRADIO_LOG_DEBUG("Unknown focus_state\n");
-               break;
+       ret = radio_hal_get_volume(radio->hal_inf, &volume);
+       if (ret != MM_ERROR_NONE) {
+               MMRADIO_LOG_ERROR("failed to get radio hal volume");
+               *pVolume = 0;
+               return ret;
        }
 
+       MMRADIO_VOLUME_LOCK(radio);
+       radio->local_volume = volume;
+       *pVolume = (float)radio->local_volume;
+       MMRADIO_VOLUME_UNLOCK(radio);
+
        MMRADIO_LOG_FLEAVE();
+
+       return ret;
 }
-#endif
 
-static int __mmradio_set_total_volume(mm_radio_t *radio)
+static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level)
 {
        int ret = MM_ERROR_NONE;
-       float total_volume = 0.0f;
+
+       MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
+       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
+
+       MMRADIO_LOG_INFO("Setting %d volume", level);
 
        MMRADIO_VOLUME_LOCK(radio);
-       if (radio->max_media_volume != 0)
-               total_volume = ((float)radio->media_volume / (float)radio->max_media_volume) * radio->local_volume;
-       else
-               MMRADIO_LOG_WARNING("max media voulme is zero");
+       radio->media_volume = level;
+       MMRADIO_VOLUME_UNLOCK(radio);
 
-       ret = radio_hal_set_volume(radio->hal_inf, total_volume);
+       ret = radio_hal_set_media_volume(radio->hal_inf, level);
        if (ret != MM_ERROR_NONE)
-               MMRADIO_LOG_ERROR("radio_hal_set_volume error");
+               MMRADIO_LOG_ERROR("failed to set radio hal media volume");
 
-       MMRADIO_VOLUME_UNLOCK(radio);
-       return ret;
+       MMRADIO_LOG_FLEAVE();
 
+       return ret;
 }
 
-static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
+static int __resource_release_cb(mm_resource_manager_h rm,
+       mm_resource_manager_res_h res, void *user_data)
 {
-       mm_radio_t *radio = (mm_radio_t *)user_data;
-       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
-       if (type == VOLUME_TYPE_MEDIA) {
-               MMRADIO_LOG_DEBUG("Change FM Radio volume to %d", volume);
-               MMRADIO_VOLUME_LOCK(radio);
-               radio->media_volume = volume;
-               MMRADIO_VOLUME_UNLOCK(radio);
-               __mmradio_set_total_volume(radio);
+       mm_radio_t *radio = NULL;
+
+       MMRADIO_LOG_FENTER();
+
+       if (!user_data) {
+               MMRADIO_LOG_ERROR("user_data is null");
+               return FALSE;
        }
+
+       radio = (mm_radio_t *)user_data;
+       radio->radio_resource = NULL;
+
+       MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
+
+       radio->interrupted_by_resource_conflict = TRUE;
+
+       MMRADIO_CMD_LOCK(radio);
+       if (_mmradio_stop(radio) != MM_ERROR_NONE)
+               MMRADIO_LOG_ERROR("failed to stop radio");
+       MMRADIO_CMD_UNLOCK(radio);
+
+       MMRADIO_LOG_FLEAVE();
+
+       return FALSE;
 }
 
-int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
+static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
 {
+       MMRadioThread_t *p_thread = NULL;
+
        MMRADIO_LOG_FENTER();
+
        MMRADIO_CHECK_INSTANCE(radio);
-       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
 
-       return_val_if_fail(type, MM_ERROR_INVALID_ARGUMENT);
+       if (type >= MM_RADIO_THREAD_NUM) {
+               MMRADIO_LOG_WARNING("wrong argument thread type");
+               return MM_ERROR_RADIO_INTERNAL;
+       }
+
+       p_thread = &radio->thread[type];
+       MMRADIO_CHECK_ARG(p_thread);
 
-       *type = radio->region_setting.country;
+       MMRADIO_INIT_MUTEX(p_thread->mutex);
+       MMRADIO_INIT_COND(p_thread->cond);
+
+       MMRADIO_THREAD_LOCK(p_thread);
+       p_thread->thread_id = pthread_create(&p_thread->thread, NULL,
+               (void *)__mmradio_thread_function[type], (void *)radio);
+       if (p_thread->thread_id) {
+               MMRADIO_LOG_DEBUG("failed to create thread : [%d]", type);
+               MMRADIO_THREAD_UNLOCK(p_thread);
+               return MM_ERROR_RADIO_INTERNAL;
+       }
+
+       MMRADIO_LOG_DEBUG("wait for [%d] thread", type);
+       MMRADIO_THREAD_WAIT(p_thread);
+       MMRADIO_LOG_DEBUG("[%d] thread started", type);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
-       MMRADIO_LOG_FLEAVE();
        return MM_ERROR_NONE;
+
+ERROR:
+       pthread_mutex_destroy(&p_thread->mutex);
+       pthread_cond_destroy(&p_thread->cond);
+       return MM_ERROR_RADIO_INTERNAL;
+
 }
 
-int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
+static int __mmradio_create_threads(mm_radio_t *radio)
 {
+       int ret = MM_ERROR_NONE;
+       int type = 0;
+
        MMRADIO_LOG_FENTER();
+
        MMRADIO_CHECK_INSTANCE(radio);
-       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
 
-       return_val_if_fail(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
+       MMRADIO_INIT_MUTEX(radio->cmd_lock);
+       MMRADIO_INIT_MUTEX(radio->volume_lock);
+       MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
 
-       *min_freq = radio->region_setting.band_min;
-       *max_freq = radio->region_setting.band_max;
+       for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
+               ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
+               if (ret) {
+                       MMRADIO_LOG_ERROR("failed to create thread(%d)", type);
+                       while (--type >= (int)MM_RADIO_THREAD_MSG)
+                               __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
+                       goto ERROR;
+               }
+       }
 
        MMRADIO_LOG_FLEAVE();
-       return MM_ERROR_NONE;
+       return ret;
+
+ERROR:
+       pthread_mutex_destroy(&radio->cmd_lock);
+       pthread_mutex_destroy(&radio->volume_lock);
+       pthread_mutex_destroy(&radio->hal_seek_mutex);
+
+       MMRADIO_LOG_FLEAVE();
+       return MM_ERROR_RADIO_INTERNAL;
 }
 
-int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
+static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
 {
+       MMRadioThread_t *p_thread = NULL;
+       mm_radio_msg_t *msg = NULL;
        MMRADIO_LOG_FENTER();
-       MMRADIO_CHECK_INSTANCE(radio);
-       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
 
-       return_val_if_fail(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       *ch_spacing = radio->region_setting.channel_spacing;
+       if (type >= MM_RADIO_THREAD_NUM) {
+               MMRADIO_LOG_WARNING("wrong argument thread type");
+               return;
+       }
+
+       p_thread = &radio->thread[type];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       if (p_thread->thread) {
+               switch (type) {
+               case MM_RADIO_THREAD_MSG:
+                       msg = g_slice_new0(mm_radio_msg_t);
+                       if (!msg) {
+                               MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
+                       } else {
+                               msg->msg_type = MM_RADIO_MSG_DESTROY;
+                               g_async_queue_push_front(radio->msg_queue, msg);
+                               pthread_join(p_thread->thread, NULL);
+                               p_thread->thread = 0;
+                       }
+                       break;
+               case MM_RADIO_THREAD_SEEK:
+               case MM_RADIO_THREAD_SCAN:
+                       MMRADIO_THREAD_LOCK(p_thread);
+                       p_thread->thread_exit = true;
+                       MMRADIO_THREAD_SIGNAL(p_thread);
+                       MMRADIO_THREAD_UNLOCK(p_thread);
+                       pthread_join(p_thread->thread, NULL);
+                       p_thread->thread = 0;
+                       break;
+               default:
+                       MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
+                       break;
+               }
+       } else {
+               MMRADIO_LOG_WARNING("(%d)thread is zero", type);
+       }
+
+       pthread_mutex_destroy(&p_thread->mutex);
+       pthread_cond_destroy(&p_thread->cond);
 
        MMRADIO_LOG_FLEAVE();
-       return MM_ERROR_NONE;
 }
 
-int _mmradio_set_volume(mm_radio_t *radio, float volume)
+static void __mmradio_destroy_threads(mm_radio_t *radio)
 {
-       int ret = MM_ERROR_NONE;
-
+       int type = (int)MM_RADIO_THREAD_NUM;
        MMRADIO_LOG_FENTER();
 
-       MMRADIO_CHECK_INSTANCE(radio);
-       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
-
-       MMRADIO_LOG_DEBUG("Setting %f volume\n", volume);
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       MMRADIO_VOLUME_LOCK(radio);
-       radio->local_volume = volume;
-       MMRADIO_VOLUME_UNLOCK(radio);
+       while (--type >= 0)
+               __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
 
-       ret = __mmradio_set_total_volume(radio);
+       pthread_mutex_destroy(&radio->cmd_lock);
+       pthread_mutex_destroy(&radio->volume_lock);
+       pthread_mutex_destroy(&radio->hal_seek_mutex);
 
        MMRADIO_LOG_FLEAVE();
-       return ret;
+}
+
+void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
+{
+       mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
+       if (!msg) {
+               MMRADIO_LOG_ERROR("NULL msg pointer");
+               return;
+       }
+
+       msg->msg_type = msg_type;
+       msg->data = msg_data;
 
+       MMRADIO_LOG_INFO("push msg_type: %d, msg_data: %d", (int)msg->msg_type, msg->data);
+       g_async_queue_push(radio->msg_queue, msg);
 }
 
-int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
+void __mmradio_msg_thread(mm_radio_t *radio)
 {
-       int ret = MM_ERROR_NONE;
-       float total_volume = 0.0;
-       float volume = 0.0;
+
+       mm_radio_msg_t *msg = NULL;
+       MMRadioThread_t *p_thread = NULL;
+
        MMRADIO_LOG_FENTER();
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       MMRADIO_CHECK_INSTANCE(radio);
-       MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
+       p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
 
-       return_val_if_fail(pVolume, MM_ERROR_INVALID_ARGUMENT);
+       p_thread->thread_exit = false;
 
-       ret = radio_hal_get_volume(radio->hal_inf, &total_volume);
-       if (ret != MM_ERROR_NONE) {
-               MMRADIO_LOG_ERROR("radio_hal_get_volume error");
-               *pVolume = 0;
-               return ret;
-       }
 
-       MMRADIO_VOLUME_LOCK(radio);
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
+
+       /* we run a while one loop*/
+       while (!p_thread->thread_exit) {
+               msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
+               if (!msg) {
+                       MMRADIO_LOG_ERROR("poped message is NULL!");
+                       break;
+               }
 
-       if (radio->media_volume)
-               volume = total_volume * ((float)radio->max_media_volume / (float)radio->media_volume);
+               MMMessageParamType param = {0,};
+
+               switch (msg->msg_type) {
+               case MM_RADIO_MSG_DESTROY:
+                       MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
+                       mm_radio_msg_t *msg_pop = NULL;
+                       while ((msg_pop = (mm_radio_msg_t *)g_async_queue_try_pop(radio->msg_queue))) {
+                               if (msg_pop != NULL) {
+                                       MMRADIO_LOG_DEBUG("drop this msg type: %d", msg_pop->msg_type);
+                                       g_slice_free(mm_radio_msg_t, msg_pop);
+                               }
+                       }
+                       p_thread->thread_exit = true;
+                       break;
+               case MM_RADIO_MSG_SCAN_INFO:
+                       MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
+                       param.radio_scan.frequency = (int) msg->data;
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
+                       break;
+               case MM_RADIO_MSG_SCAN_STOPPED:
+                       MMRADIO_LOG_INFO("get scan stopped");
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
+                       break;
+               case MM_RADIO_MSG_SCAN_FINISHED:
+                       MMRADIO_LOG_INFO("get scan finished");
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
+                       break;
+               case MM_RADIO_MSG_SEEK_FINISHED:
+                       MMRADIO_LOG_INFO("get seek finish frequency: %d", msg->data);
+                       param.radio_scan.frequency = (int) msg->data;
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
+                       break;
+               case MM_RADIO_MSG_STATE_INTERRUPTED:
+                       MMRADIO_LOG_INFO("get state interrupted type: %d", msg->data);
+                       param.union_type = MM_MSG_UNION_STATE;
+                       param.state.previous = radio->old_state;
+                       param.state.current = radio->current_state;
+                       param.state.code = msg->data;
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_STATE_INTERRUPTED, &param);
+                       break;
+               default:
+                       MMRADIO_LOG_ERROR("wrong msg_type : %d", msg->msg_type);
+                       break;
+               }
 
-       MMRADIO_LOG_DEBUG("total_volume = %f, max_media_volue = %d, media_volume = %d, volume = %f",
-               total_volume, radio->max_media_volume, radio->media_volume, volume);
+               if (msg)
+                       g_slice_free(mm_radio_msg_t, msg);
 
-       /* update volume in handle */
-       if (fabs(radio->local_volume - volume) >= FLT_EPSILON) {
-               radio->local_volume = volume;
        }
 
-       *pVolume = (float)radio->local_volume;
-       MMRADIO_VOLUME_UNLOCK(radio);
-
+       MMRADIO_LOG_INFO("msg thread is finished");
        MMRADIO_LOG_FLEAVE();
-
-       return ret;
+       pthread_exit(NULL);
 }
-