Add null check when destroy sound manager vstream
[platform/core/multimedia/libmm-radio.git] / src / mm_radio_priv_hal.c
old mode 100755 (executable)
new mode 100644 (file)
index 44d5bf5..ac1cd92
@@ -123,13 +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);
-static int __mmradio_create_thread(mm_radio_t *radio);
-static void __mmradio_destroy_thread(mm_radio_t *radio);
+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_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)
 {
@@ -185,12 +196,21 @@ int _mmradio_create_radio(mm_radio_t *radio)
        radio->freq = DEFAULT_FREQ;
        memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
        radio->local_volume = 1.0;
+       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;
+       }
 
        /* create mutex and thread */
-       ret = __mmradio_create_thread(radio);
+       ret = __mmradio_create_threads(radio);
        if (ret) {
                MMRADIO_LOG_ERROR("failed to create threads");
-               return ret;
+               goto ERROR_THREAD;
        }
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
@@ -200,18 +220,28 @@ int _mmradio_create_radio(mm_radio_t *radio)
                        __resource_release_cb, radio, &radio->resource_manager);
        if (ret) {
                MMRADIO_LOG_ERROR("failed to create resource manager");
-               return MM_ERROR_RADIO_INTERNAL;
+               ret = MM_ERROR_RADIO_INTERNAL;
+               goto ERROR_RESOURCE;
        }
 
        ret = radio_hal_interface_init(&(radio->hal_inf));
        if (ret) {
                MMRADIO_LOG_ERROR("failed to init mmradio hal interface");
-               return ret;
+               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)
@@ -301,8 +331,14 @@ int _mmradio_unrealize(mm_radio_t *radio)
        _mmradio_stop(radio);
 
 #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
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
@@ -323,7 +359,10 @@ int _mmradio_destroy(mm_radio_t *radio)
        _mmradio_unrealize(radio);
 
        /* destroy mutex and thread */
-       __mmradio_destroy_thread(radio);
+       __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) {
@@ -651,13 +690,17 @@ 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->seek.is_running) {
+       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;
        }
@@ -677,10 +720,10 @@ int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
 
        MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
        radio->seek_direction = direction;
-       radio->seek.is_running = true;
-       radio->seek.stop = false;
+       p_thread->is_running = true;
+       p_thread->stop = false;
 
-       MMRADIO_SEEK_THREAD_SIGNAL(radio);
+       MMRADIO_THREAD_SIGNAL(p_thread);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -694,7 +737,7 @@ void _mmradio_seek_cancel(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
        /* cancel any outstanding seek request */
-       radio->seek.stop = true;
+       radio->thread[MM_RADIO_THREAD_SEEK].stop = true;
 
        MMRADIO_LOG_FLEAVE();
 }
@@ -702,13 +745,17 @@ void _mmradio_seek_cancel(mm_radio_t *radio)
 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);
 
-       radio->scan.stop = false;
+       p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
+       MMRADIO_CHECK_ARG(p_thread);
+
+       p_thread->stop = false;
 
        if (!radio->is_ready) {
                ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
@@ -750,9 +797,9 @@ int _mmradio_start_scan(mm_radio_t *radio)
                MMRADIO_LOG_DEBUG("radio prepared and opened");
        }
 
-       radio->scan.is_running = true;
+       p_thread->is_running = true;
 
-       MMRADIO_SCAN_THREAD_SIGNAL(radio);
+       MMRADIO_THREAD_SIGNAL(p_thread);
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
@@ -768,7 +815,7 @@ int _mmradio_stop_scan(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
 
-       radio->scan.stop = true;
+       radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
 
        MMRADIO_LOG_FLEAVE();
 
@@ -804,26 +851,37 @@ 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);
 
-       MMRADIO_SCAN_THREAD_LOCK(radio);
+       p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
-       while (!radio->scan.thread_exit) {
+       MMRADIO_THREAD_LOCK(p_thread);
+
+       while (!p_thread->thread_exit) {
                MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
-               MMRADIO_SCAN_THREAD_WAIT(radio);
+               MMRADIO_THREAD_WAIT(p_thread);
 
-               if (radio->scan.thread_exit) {
+               if (p_thread->thread_exit) {
                        MMRADIO_LOG_DEBUG("exiting scan thread");
                        goto EXIT;
                }
 
-               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;
+               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_set_frequency(radio->hal_inf, radio->region_setting.band_min);
@@ -833,19 +891,18 @@ void __mmradio_scan_thread(mm_radio_t *radio)
                MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
                MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
-               while (!radio->scan.stop) {
+               prev_freq = 0;
+               while (!p_thread->stop) {
                        uint32_t freq = 0;
-                       prev_freq = 0;
-                       MMMessageParamType param = { 0, };
 
                        MMRADIO_LOG_DEBUG("scanning....");
 
-                       if (radio->scan.thread_exit) {
+                       if (p_thread->thread_exit) {
                                MMRADIO_LOG_DEBUG("exiting scan thread");
                                goto EXIT;
                        }
 
-                       if (radio->scan.stop) {
+                       if (p_thread->stop) {
                                MMRADIO_LOG_INFO("scan was canceled");
                                goto FINISHED;
                        }
@@ -858,12 +915,12 @@ void __mmradio_scan_thread(mm_radio_t *radio)
                                break;
                        }
 
-                       if (radio->scan.thread_exit) {
+                       if (p_thread->thread_exit) {
                                MMRADIO_LOG_DEBUG("exiting scan thread");
                                goto EXIT;
                        }
 
-                       if (radio->scan.stop) {
+                       if (p_thread->stop) {
                                MMRADIO_LOG_INFO("scan was canceled");
                                goto FINISHED;
                        }
@@ -878,21 +935,21 @@ void __mmradio_scan_thread(mm_radio_t *radio)
                                        break;
                                }
 
-                               prev_freq = param.radio_scan.frequency = (int)freq;
-                               MMRADIO_LOG_INFO("scanning : new frequency : [%d]", param.radio_scan.frequency);
+                               prev_freq = (int)freq;
+                               MMRADIO_LOG_INFO("scanning : new frequency : [%d]", prev_freq);
 
                                /* drop if max freq is scanned */
-                               if (param.radio_scan.frequency >= radio->region_setting.band_max) {
-                                       MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", param.radio_scan.frequency);
+                               if (prev_freq >= radio->region_setting.band_max) {
+                                       MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", prev_freq);
                                        break;
                                }
 
-                               if (radio->scan.stop) {
+                               if (p_thread->stop) {
                                        /* doesn't need to post */
                                        break;
                                }
 
-                               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
+                               __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
                        }
                }
 
@@ -952,19 +1009,19 @@ FINISHED_ERR:
                        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
                }
 
-               if (!radio->scan.stop)
-                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
+               if (!p_thread->stop)
+                       __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
                else
-                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
+                       __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
 
-               radio->scan.is_running = false;
+               p_thread->is_running = false;
 
        }
 
 EXIT:
-       radio->scan.is_running = false;
+       p_thread->is_running = false;
 
-       MMRADIO_SCAN_THREAD_UNLOCK(radio);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -991,18 +1048,25 @@ 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_SEEK_THREAD_LOCK(radio);
+       p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
-       while (!radio->seek.thread_exit) {
+       MMRADIO_THREAD_LOCK(p_thread);
+
+       while (!p_thread->thread_exit) {
                MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.");
-               MMRADIO_SEEK_THREAD_WAIT(radio);
+               MMRADIO_THREAD_WAIT(p_thread);
 
-               if (radio->seek.thread_exit) {
+               if (p_thread->thread_exit) {
                        MMRADIO_LOG_DEBUG("exiting seek thread");
                        goto EXIT;
                }
@@ -1010,7 +1074,7 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
                MMRADIO_LOG_DEBUG("seeking....");
 
-               if (radio->seek.stop) {
+               if (p_thread->stop) {
                        MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
                        goto SEEK_FAILED;
                }
@@ -1025,12 +1089,12 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                        goto SEEK_FAILED;
                }
 
-               if (radio->seek.thread_exit) {
+               if (p_thread->thread_exit) {
                        MMRADIO_LOG_DEBUG("exiting seek thread");
                        goto EXIT;
                }
 
-               if (radio->seek.stop) {
+               if (p_thread->stop) {
                        MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
                        goto SEEK_FAILED;
                }
@@ -1075,10 +1139,10 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                        radio->seek_unmute = false;
                }
 
-               param.radio_scan.frequency = radio->prev_seek_freq = (int)freq;
-               MMRADIO_LOG_INFO("seeking : new frequency : [%d]", param.radio_scan.frequency);
-               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
-               radio->seek.is_running = false;
+               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:
@@ -1093,14 +1157,13 @@ SEEK_FAILED:
                        radio->seek_unmute = 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->seek.is_running = false;
+               __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
+               p_thread->is_running = false;
        }
 
 EXIT:
-       radio->seek.is_running = false;
-       MMRADIO_SEEK_THREAD_UNLOCK(radio);
+       p_thread->is_running = false;
+       MMRADIO_THREAD_UNLOCK(p_thread);
        MMRADIO_LOG_FLEAVE();
        pthread_exit(NULL);
 }
@@ -1285,9 +1348,8 @@ static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
        msg.state.current = radio->current_state;
 
        if (radio->interrupted_by_resource_conflict) {
-               msg_type = MM_MESSAGE_STATE_INTERRUPTED;
-               msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
-               MMRADIO_POST_MSG(radio, msg_type, &msg);
+               __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);
@@ -1470,97 +1532,245 @@ static int __resource_release_cb(mm_resource_manager_h rm,
        return FALSE;
 }
 
-static int __mmradio_create_thread(mm_radio_t *radio)
+static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
 {
-       int ret = MM_ERROR_NONE;
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
 
-       MMRADIO_INIT_MUTEX(radio->cmd_lock);
-       MMRADIO_INIT_MUTEX(radio->volume_lock);
-       MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
+       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);
 
-       MMRADIO_INIT_MUTEX(radio->seek.mutex);
-       MMRADIO_INIT_COND(radio->seek.cond);
+       MMRADIO_INIT_MUTEX(p_thread->mutex);
+       MMRADIO_INIT_COND(p_thread->cond);
 
-       radio->seek.thread_id = pthread_create(&radio->seek.thread, NULL,
-               (void *)__mmradio_seek_thread, (void *)radio);
-       if (radio->seek.thread_id) {
-               MMRADIO_LOG_DEBUG("failed to create thread : seek");
-               goto ERROR;
+       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_INIT_MUTEX(radio->scan.mutex);
-       MMRADIO_INIT_COND(radio->scan.cond);
+       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);
+
+       return MM_ERROR_NONE;
+
+ERROR:
+       pthread_mutex_destroy(&p_thread->mutex);
+       pthread_cond_destroy(&p_thread->cond);
+       return MM_ERROR_RADIO_INTERNAL;
+
+}
+
+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_INIT_MUTEX(radio->cmd_lock);
+       MMRADIO_INIT_MUTEX(radio->volume_lock);
+       MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
 
-       radio->scan.thread_id = pthread_create(&radio->scan.thread, NULL,
-               (void *)__mmradio_scan_thread, (void *)radio);
-       if (radio->scan.thread_id) {
-               MMRADIO_LOG_ERROR("failed to create thread : scan");
-               goto ERROR;
+       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 ret;
 
 ERROR:
-
-       if (radio->seek.thread) {
-               MMRADIO_SEEK_THREAD_LOCK(radio);
-               radio->seek.thread_exit = true;
-               MMRADIO_SEEK_THREAD_SIGNAL(radio);
-               MMRADIO_SEEK_THREAD_UNLOCK(radio);
-               pthread_join(radio->seek.thread, NULL);
-               radio->seek.thread = 0;
-       }
-
        pthread_mutex_destroy(&radio->cmd_lock);
        pthread_mutex_destroy(&radio->volume_lock);
        pthread_mutex_destroy(&radio->hal_seek_mutex);
-       pthread_mutex_destroy(&radio->seek.mutex);
-       pthread_cond_destroy(&radio->seek.cond);
-       pthread_mutex_destroy(&radio->scan.mutex);
-       pthread_cond_destroy(&radio->scan.cond);
 
+       MMRADIO_LOG_FLEAVE();
        return MM_ERROR_RADIO_INTERNAL;
 }
 
-static void __mmradio_destroy_thread(mm_radio_t *radio)
+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_RETURN_VOID(radio);
 
-       if (radio->seek.thread) {
-               MMRADIO_SEEK_THREAD_LOCK(radio);
-               radio->seek.thread_exit = true;
-               MMRADIO_SEEK_THREAD_SIGNAL(radio);
-               MMRADIO_SEEK_THREAD_UNLOCK(radio);
-               pthread_join(radio->seek.thread, NULL);
-               radio->seek.thread = 0;
+       if (type >= MM_RADIO_THREAD_NUM) {
+               MMRADIO_LOG_WARNING("wrong argument thread type");
+               return;
        }
 
-       if (radio->scan.thread) {
-               MMRADIO_SCAN_THREAD_LOCK(radio);
-               radio->scan.thread_exit = true;
-               MMRADIO_SCAN_THREAD_SIGNAL(radio);
-               MMRADIO_SCAN_THREAD_UNLOCK(radio);
-               pthread_join(radio->scan.thread, NULL);
-               radio->scan.thread = 0;
+       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();
+}
+
+static void __mmradio_destroy_threads(mm_radio_t *radio)
+{
+       int type = (int)MM_RADIO_THREAD_NUM;
+       MMRADIO_LOG_FENTER();
+
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
+
+       while (--type >= 0)
+               __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
+
        pthread_mutex_destroy(&radio->cmd_lock);
        pthread_mutex_destroy(&radio->volume_lock);
        pthread_mutex_destroy(&radio->hal_seek_mutex);
 
-       pthread_mutex_destroy(&radio->seek.mutex);
-       pthread_cond_destroy(&radio->seek.cond);
+       MMRADIO_LOG_FLEAVE();
+}
 
-       pthread_mutex_destroy(&radio->scan.mutex);
-       pthread_cond_destroy(&radio->scan.cond);
+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;
+       }
 
-       MMRADIO_LOG_FLEAVE();
+       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);
+}
+
+void __mmradio_msg_thread(mm_radio_t *radio)
+{
+
+       mm_radio_msg_t *msg = NULL;
+       MMRadioThread_t *p_thread = NULL;
+
+       MMRADIO_LOG_FENTER();
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
+
+       p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       p_thread->thread_exit = false;
 
+
+       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;
+               }
+
+               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;
+               }
+
+               if (msg)
+                       g_slice_free(mm_radio_msg_t, msg);
+
+       }
+
+       MMRADIO_LOG_INFO("msg thread is finished");
+       MMRADIO_LOG_FLEAVE();
+       pthread_exit(NULL);
 }