Messages related to callback are posted using thread 85/174885/2
authorGilbok Lee <gilbok.lee@samsung.com>
Thu, 11 Jan 2018 09:51:22 +0000 (18:51 +0900)
committerGilbok Lee <gilbok.lee@samsung.com>
Thu, 5 Apr 2018 01:28:48 +0000 (10:28 +0900)
[Version] 0.2.37
[Profile] Mobile, Wearable
[Issue Type] Fix bugs

Change-Id: I22f3d33f0f9ae30fa8bd3ce4251e2d094af17814

packaging/libmm-radio.spec
src/include/mm_radio_priv.h
src/include/mm_radio_priv_hal.h
src/mm_radio_priv_emulator.c
src/mm_radio_priv_hal.c [changed mode: 0755->0644]

index 84a7ade..66a472d 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       libmm-radio
 Summary:    Multimedia Framework Radio Library
-Version:    0.2.36
+Version:    0.2.37
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 7870aab..1c7d6df 100644 (file)
@@ -41,6 +41,8 @@
 #include <gst/gst.h>
 #include <gst/gstbuffer.h>
 
+#include <glib.h>
+
 #ifdef __cplusplus
        extern "C" {
 #endif
@@ -133,6 +135,22 @@ typedef struct {
        bool thread_exit;
 } MMRadioThread_t;
 
+typedef enum {
+       MM_RADIO_MSG_DESTROY = 0,
+       MM_RADIO_MSG_SCAN_INFO,
+       MM_RADIO_MSG_SCAN_STOPPED,
+       MM_RADIO_MSG_SCAN_FINISHED,
+       MM_RADIO_MSG_SEEK_FINISHED,
+       MM_RADIO_MSG_STATE_INTERRUPTED,
+       MM_RADIO_MSG_NUM
+} MMRadioMsgTypes;
+
+typedef struct {
+       bool destroy;
+       MMRadioMsgTypes msg_type;
+       int data;
+} mm_radio_msg_t;
+
 /*---------------------------------------------------------------------------
     GLOBAL DATA TYPE DEFINITIONS:
 ---------------------------------------------------------------------------*/
@@ -165,6 +183,8 @@ typedef struct {
        MMHandleType* attrs;
 
        /* message callback */
+       GAsyncQueue *msg_queue;
+       MMRadioThread_t msg;
        MMMessageCallback msg_cb;
        void* msg_cb_param;
 
index 2a68170..ed80aee 100644 (file)
@@ -44,6 +44,8 @@
 #include "radio_hal_interface.h"
 #include <linux/videodev2.h>
 
+#include <glib.h>
+
 #ifdef __cplusplus
        extern "C" {
 #endif
@@ -137,6 +139,22 @@ typedef struct {
        bool thread_exit;
 } MMRadioThread_t;
 
+typedef enum {
+       MM_RADIO_MSG_DESTROY = 0,
+       MM_RADIO_MSG_SCAN_INFO,
+       MM_RADIO_MSG_SCAN_STOPPED,
+       MM_RADIO_MSG_SCAN_FINISHED,
+       MM_RADIO_MSG_SEEK_FINISHED,
+       MM_RADIO_MSG_STATE_INTERRUPTED,
+       MM_RADIO_MSG_NUM
+} MMRadioMsgTypes;
+
+typedef struct {
+       bool destroy;
+       MMRadioMsgTypes msg_type;
+       int data;
+} mm_radio_msg_t;
+
 /*---------------------------------------------------------------------------
     GLOBAL DATA TYPE DEFINITIONS:
 ---------------------------------------------------------------------------*/
@@ -156,6 +174,8 @@ typedef struct {
        MMHandleType *attrs;
 
        /* message callback */
+       GAsyncQueue *msg_queue;
+       MMRadioThread_t msg;
        MMMessageCallback msg_cb;
        void *msg_cb_param;
 
index 21d211a..21f0f11 100644 (file)
@@ -133,6 +133,8 @@ static int __mmradio_set_band_range(mm_radio_t * radio);
 static int __mmradio_get_wave_num(mm_radio_t * radio);
 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);
 /*===========================================================================
   FUNCTION DEFINITIONS
 ========================================================================== */
@@ -218,11 +220,18 @@ int _mmradio_create_radio(mm_radio_t * radio)
        radio->subs_id = 0;
        radio->local_volume = 1.0;
 
+       /* 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);
        if (ret) {
                MMRADIO_LOG_ERROR("failed to create threads");
-               return ret;
+               goto ERROR_THREAD;
        }
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
@@ -232,12 +241,20 @@ 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;
        }
 
        MMRADIO_LOG_FLEAVE();
 
        return MM_ERROR_NONE;
+
+ERROR_RESOURCE:
+       __mmradio_destroy_thread(radio);
+ERROR_THREAD:
+       if (radio->msg_queue)
+               g_async_queue_unref(radio->msg_queue);
+       return ret;
 }
 
 int _mmradio_realize(mm_radio_t *radio)
@@ -335,6 +352,9 @@ int _mmradio_destroy(mm_radio_t * radio)
        /* destroy mutex and thread */
        __mmradio_destroy_thread(radio);
 
+       if (radio->msg_queue)
+               g_async_queue_unref(radio->msg_queue);
+
        ret = mm_resource_manager_destroy(radio->resource_manager);
        if (ret) {
                MMRADIO_LOG_ERROR("failed to destroy resource manager");
@@ -879,7 +899,6 @@ void __mmradio_scan_thread(mm_radio_t * radio)
 
                while (!radio->scan.stop) {
 
-                       MMMessageParamType param = { 0, };
                        freq = 0;
 
                        MMRADIO_LOG_DEBUG("scanning....");
@@ -913,21 +932,20 @@ void __mmradio_scan_thread(mm_radio_t * radio)
                        if (freq == prev_freq)
                                continue;
 
-                       prev_freq = param.radio_scan.frequency = freq;
-                       MMRADIO_SLOG_DEBUG("scanning : new frequency : [%d]", param.radio_scan.frequency);
+                       prev_freq = freq;
+                       MMRADIO_LOG_INFO("scanning : new frequency : [%d]", freq);
 
                        /* drop if max freq is scanned */
-                       if (param.radio_scan.frequency == radio->region_setting.band_max
-                           || param.radio_scan.frequency > radio->region_setting.band_max
-                           || param.radio_scan.frequency < radio->region_setting.band_min) {
-                               MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan", param.radio_scan.frequency);
+                       if (freq >= radio->region_setting.band_max
+                           || freq < radio->region_setting.band_min) {
+                               MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan", freq);
                                break;
                        }
 
                        if (radio->scan.stop)
                                break;                  /* doesn't need to post */
 
-                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
+                       __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
                        emulatoridx++;
                        if (emulatoridx >= EMULATOR_FREQ_MAX)
                                break;
@@ -948,9 +966,9 @@ FINISHED:
                }
 
                if (!radio->scan.stop)
-                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
+                       __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;
                radio->scan.stop = false;
@@ -982,7 +1000,6 @@ void __mmradio_seek_thread(mm_radio_t * radio)
        int freq = 0;
        int i = 0;
        int emulatoridx = 0;
-       MMMessageParamType param = { 0, };
 
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
@@ -1056,17 +1073,16 @@ void __mmradio_seek_thread(mm_radio_t * radio)
                        }
                }
 
-               param.radio_scan.frequency = radio->prev_seek_freq = freq;
-               MMRADIO_SLOG_DEBUG("seeking : new frequency : [%d]", param.radio_scan.frequency);
-               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
+               radio->prev_seek_freq = freq;
+               MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
+               __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
                radio->seek.stop = true;
                radio->seek.is_running = false;
                continue;
 
 SEEK_FAILED:
                /* freq -1 means it's failed to seek */
-               param.radio_scan.frequency = -1;
-               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
+               __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
                radio->seek.stop = true;
                radio->seek.is_running = false;
        }
@@ -1255,9 +1271,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);
@@ -1446,6 +1461,14 @@ static int __mmradio_create_thread(mm_radio_t *radio)
 
        MMRADIO_INIT_MUTEX(radio->cmd_lock);
 
+       radio->msg.thread_id = pthread_create(&radio->msg.thread, NULL,
+               (void *)__mmradio_msg_thread, (void *)radio);
+       if (radio->msg.thread_id) {
+               /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
+               MMRADIO_LOG_ERROR("failed to create thread : msg");
+               goto ERROR;
+       }
+
        MMRADIO_INIT_MUTEX(radio->seek.mutex);
        MMRADIO_INIT_COND(radio->seek.cond);
 
@@ -1471,7 +1494,6 @@ static int __mmradio_create_thread(mm_radio_t *radio)
        return ret;
 
 ERROR:
-
        if (radio->seek.thread) {
                MMRADIO_SEEK_THREAD_LOCK(radio);
                radio->seek.thread_exit = true;
@@ -1481,6 +1503,18 @@ ERROR:
                radio->seek.thread = 0;
        }
 
+       if (radio->msg.thread) {
+               mm_radio_msg_t *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(radio->msg.thread, NULL);
+                       radio->msg.thread = 0;
+               }
+       }
+
        pthread_mutex_destroy(&radio->cmd_lock);
        pthread_mutex_destroy(&radio->seek.mutex);
        pthread_cond_destroy(&radio->seek.cond);
@@ -1514,6 +1548,18 @@ static void __mmradio_destroy_thread(mm_radio_t *radio)
                radio->scan.thread = 0;
        }
 
+       if (radio->msg.thread) {
+               mm_radio_msg_t *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(radio->msg.thread, NULL);
+                       radio->msg.thread = 0;
+               }
+       }
+
        pthread_mutex_destroy(&radio->cmd_lock);
 
        pthread_mutex_destroy(&radio->seek.mutex);
@@ -1522,5 +1568,83 @@ static void __mmradio_destroy_thread(mm_radio_t *radio)
        pthread_cond_destroy(&radio->scan.cond);
 
        MMRADIO_LOG_FLEAVE();
+}
+
+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);
+}
+
+void __mmradio_msg_thread(mm_radio_t *radio)
+{
+       MMMessageParamType param = {0,};
+       mm_radio_msg_t *msg = NULL;
+       int exit_msg_thread = 0;
+
+       /*we run a while one loop*/
+       while (exit_msg_thread == 0) {
+               msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
+               if (!msg) {
+                       MMRADIO_LOG_ERROR("poped message is NULL!");
+                       break;
+               }
+
+               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);
+                               }
+                       }
+                       exit_msg_thread = 1;
+                       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 finished 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");
 }
old mode 100755 (executable)
new mode 100644 (file)
index 44d5bf5..5dab31b
@@ -130,6 +130,8 @@ static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume,
 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);
 
 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
 {
@@ -186,11 +188,18 @@ int _mmradio_create_radio(mm_radio_t *radio)
        memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
        radio->local_volume = 1.0;
 
+       /* 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);
        if (ret) {
                MMRADIO_LOG_ERROR("failed to create threads");
-               return ret;
+               goto ERROR_THREAD;
        }
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
@@ -200,18 +209,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_thread(radio);
+ERROR_THREAD:
+       if (radio->msg_queue)
+               g_async_queue_unref(radio->msg_queue);
+       return ret;
 }
 
 int _mmradio_realize(mm_radio_t *radio)
@@ -325,6 +344,9 @@ int _mmradio_destroy(mm_radio_t *radio)
        /* destroy mutex and thread */
        __mmradio_destroy_thread(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("failed to deinitialize radio hal interface");
@@ -833,10 +855,9 @@ 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);
 
+               prev_freq = 0;
                while (!radio->scan.stop) {
                        uint32_t freq = 0;
-                       prev_freq = 0;
-                       MMMessageParamType param = { 0, };
 
                        MMRADIO_LOG_DEBUG("scanning....");
 
@@ -878,12 +899,12 @@ 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;
                                }
 
@@ -892,7 +913,7 @@ void __mmradio_scan_thread(mm_radio_t *radio)
                                        break;
                                }
 
-                               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
+                               __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
                        }
                }
 
@@ -953,9 +974,9 @@ FINISHED_ERR:
                }
 
                if (!radio->scan.stop)
-                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
+                       __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;
 
@@ -991,7 +1012,6 @@ void __mmradio_seek_thread(mm_radio_t *radio)
 {
        int ret = MM_ERROR_NONE;
        uint32_t freq = 0;
-       MMMessageParamType param = {0, };
 
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
@@ -1075,9 +1095,9 @@ 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->prev_seek_freq = (int)freq;
+               MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
+               __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
                radio->seek.is_running = false;
                continue;
 
@@ -1093,8 +1113,7 @@ 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);
+               __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
                radio->seek.is_running = false;
        }
 
@@ -1285,9 +1304,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);
@@ -1482,6 +1500,14 @@ static int __mmradio_create_thread(mm_radio_t *radio)
        MMRADIO_INIT_MUTEX(radio->volume_lock);
        MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
 
+       radio->msg.thread_id = pthread_create(&radio->msg.thread, NULL,
+               (void *)__mmradio_msg_thread, (void *)radio);
+       if (radio->msg.thread_id) {
+               /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
+               MMRADIO_LOG_ERROR("failed to create thread : msg");
+               goto ERROR;
+       }
+
        MMRADIO_INIT_MUTEX(radio->seek.mutex);
        MMRADIO_INIT_COND(radio->seek.cond);
 
@@ -1506,7 +1532,6 @@ static int __mmradio_create_thread(mm_radio_t *radio)
        return ret;
 
 ERROR:
-
        if (radio->seek.thread) {
                MMRADIO_SEEK_THREAD_LOCK(radio);
                radio->seek.thread_exit = true;
@@ -1516,6 +1541,18 @@ ERROR:
                radio->seek.thread = 0;
        }
 
+       if (radio->msg.thread) {
+               mm_radio_msg_t *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(radio->msg.thread, NULL);
+                       radio->msg.thread = 0;
+               }
+       }
+
        pthread_mutex_destroy(&radio->cmd_lock);
        pthread_mutex_destroy(&radio->volume_lock);
        pthread_mutex_destroy(&radio->hal_seek_mutex);
@@ -1551,6 +1588,18 @@ static void __mmradio_destroy_thread(mm_radio_t *radio)
                radio->scan.thread = 0;
        }
 
+       if (radio->msg.thread) {
+               mm_radio_msg_t *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(radio->msg.thread, NULL);
+                       radio->msg.thread = 0;
+               }
+       }
+
        pthread_mutex_destroy(&radio->cmd_lock);
        pthread_mutex_destroy(&radio->volume_lock);
        pthread_mutex_destroy(&radio->hal_seek_mutex);
@@ -1562,5 +1611,84 @@ static void __mmradio_destroy_thread(mm_radio_t *radio)
        pthread_cond_destroy(&radio->scan.cond);
 
        MMRADIO_LOG_FLEAVE();
+}
+
+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);
+}
+
+void __mmradio_msg_thread(mm_radio_t *radio)
+{
+       MMMessageParamType param = {0,};
+       mm_radio_msg_t *msg = NULL;
+       int exit_msg_thread = 0;
+
+       /*we run a while one loop*/
+       while (exit_msg_thread == 0) {
+               msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
+               if (!msg) {
+                       MMRADIO_LOG_ERROR("poped message is NULL!");
+                       break;
+               }
+
+               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);
+                               }
+                       }
+                       exit_msg_thread = 1;
+                       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");
 }