Create seek/scan thread once when radio handle create. 94/173994/7
authorGilbok Lee <gilbok.lee@samsung.com>
Tue, 27 Mar 2018 10:16:41 +0000 (19:16 +0900)
committerGilbok Lee <gilbok.lee@samsung.com>
Fri, 30 Mar 2018 05:19:46 +0000 (14:19 +0900)
[Version] 0.2.35
[Profile] Mobile, Wearable
[Issue Type] Refactoring

Change-Id: Ie41d3190074310e94a180ca3f45c9e0ce5e865f7

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

index 9072a22..59cc0ce 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       libmm-radio
 Summary:    Multimedia Framework Radio Library
-Version:    0.2.34
+Version:    0.2.35
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
old mode 100755 (executable)
new mode 100644 (file)
index f6ad141..db0acfd
@@ -127,6 +127,16 @@ typedef struct {
        int channel_spacing;                            // TBD
 } MMRadioRegion_t;
 
+typedef struct {
+       pthread_t thread;
+       pthread_mutex_t mutex;
+       pthread_cond_t cond;
+       int thread_id;
+       bool is_running;
+       bool stop;
+       bool thread_exit;
+} MMRadioThread_t;
+
 /*---------------------------------------------------------------------------
     GLOBAL DATA TYPE DEFINITIONS:
 ---------------------------------------------------------------------------*/
@@ -175,11 +185,10 @@ typedef struct {
        struct v4l2_dbg_register reg;
 
        /* scan */
-       pthread_t       scan_thread;
-       bool    stop_scan;
+       MMRadioThread_t scan;
 
        /* seek */
-       pthread_t seek_thread;
+       MMRadioThread_t seek;
        int prev_seek_freq;
        MMRadioSeekDirectionType seek_direction;
 
index 437a40e..d3acdaa 100755 (executable)
@@ -131,6 +131,16 @@ typedef struct {
        int channel_spacing;                            // TBD
 } MMRadioRegion_t;
 
+typedef struct {
+       pthread_t thread;
+       pthread_mutex_t mutex;
+       pthread_cond_t cond;
+       int thread_id;
+       bool is_running;
+       bool stop;
+       bool thread_exit;
+} MMRadioThread_t;
+
 /*---------------------------------------------------------------------------
     GLOBAL DATA TYPE DEFINITIONS:
 ---------------------------------------------------------------------------*/
@@ -154,20 +164,16 @@ typedef struct {
        void *msg_cb_param;
 
        /* scan */
-       pthread_t scan_thread;
-       bool stop_scan;
+       MMRadioThread_t scan;
 
        /* seek */
-       pthread_t seek_thread;
-       pthread_mutex_t seek_cancel_mutex;
-       bool stop_seek;
-       bool is_seeking;
+       MMRadioThread_t seek;
        int prev_seek_freq;
-       int is_muted;
-       int is_ready;
+       bool is_muted;
+       bool seek_unmute;
+       bool is_ready;
 
-       int seek_unmute;
-       bool seek_cancel;
+       pthread_mutex_t hal_seek_mutex;
 
        MMRadioSeekDirectionType seek_direction;
 
index bcc5959..b538b6d 100644 (file)
@@ -112,6 +112,22 @@ do {                                                                                                               \
 #define MMRADIO_VOLUME_LOCK(x_radio)           pthread_mutex_lock(&((mm_radio_t *)x_radio)->volume_lock)
 #define MMRADIO_VOLUME_UNLOCK(x_radio)         pthread_mutex_unlock(&((mm_radio_t *)x_radio)->volume_lock)
 
+/* seek thread */
+#define MMRADIO_SEEK_THREAD_LOCK(x_radio)      pthread_mutex_lock(&((mm_radio_t *)x_radio)->seek.mutex)
+#define MMRADIO_SEEK_THREAD_UNLOCK(x_radio)    pthread_mutex_unlock(&((mm_radio_t *)x_radio)->seek.mutex)
+#define MMRADIO_SEEK_THREAD_WAIT(x_radio)      pthread_cond_wait(&((mm_radio_t *)x_radio)->seek.cond, &((mm_radio_t *)x_radio)->seek.mutex)
+#define MMRADIO_SEEK_THREAD_SIGNAL(x_radio)    pthread_cond_signal(&((mm_radio_t *)x_radio)->seek.cond)
+
+/* scan thread */
+#define MMRADIO_SCAN_THREAD_LOCK(x_radio)      pthread_mutex_lock(&((mm_radio_t *)x_radio)->scan.mutex)
+#define MMRADIO_SCAN_THREAD_UNLOCK(x_radio)    pthread_mutex_unlock(&((mm_radio_t *)x_radio)->scan.mutex)
+#define MMRADIO_SCAN_THREAD_WAIT(x_radio)      pthread_cond_wait(&((mm_radio_t *)x_radio)->scan.cond, &((mm_radio_t *)x_radio)->scan.mutex)
+#define MMRADIO_SCAN_THREAD_SIGNAL(x_radio)    pthread_cond_signal(&((mm_radio_t *)x_radio)->scan.cond)
+
+/* hal seek thread */
+#define MMRADIO_HAL_SEEK_THREAD_LOCK(x_radio)  pthread_mutex_lock(&((mm_radio_t *)x_radio)->hal_seek_mutex)
+#define MMRADIO_HAL_SEEK_THREAD_UNLOCK(x_radio)        pthread_mutex_unlock(&((mm_radio_t *)x_radio)->hal_seek_mutex)
+
 /* message posting */
 #define MMRADIO_POST_MSG(x_radio, x_msgtype, x_msg_param)              \
 do {                                                                                                                   \
@@ -146,10 +162,26 @@ do {                                                                                                                                      \
 #define MMRADIO_CHECK_RETURN_IF_FAIL(x_ret, x_msg)             \
 do {                                                                                                   \
        if (x_ret < 0) {                                                                        \
-               MMRADIO_LOG_ERROR("%s error\n", x_msg);                         \
+               MMRADIO_LOG_ERROR("%s error\n", x_msg);                 \
                return x_ret;                                                                   \
        }                                                                                                       \
 } while (0);
 
+#define MMRADIO_INIT_MUTEX(x_mutex)                                    \
+do {                                                                                                   \
+       if (pthread_mutex_init(&x_mutex, NULL) < 0) {           \
+               MMRADIO_LOG_ERROR("failed to create mutex");    \
+               goto ERROR;                                                                     \
+       }                                                                                                       \
+} while (0)
+
+#define MMRADIO_INIT_COND(x_cond)                                              \
+do {                                                                                                   \
+       if (pthread_cond_init(&x_cond, NULL) < 0) {                     \
+               MMRADIO_LOG_ERROR("failed to create cond");     \
+               goto ERROR;                                                                     \
+       }                                                                                                       \
+} while (0)
+
 #endif
 
old mode 100755 (executable)
new mode 100644 (file)
index d79c12c..5bb4de0
@@ -122,8 +122,6 @@ static int MMRadioEmulatorFreq[EMULATOR_FREQ_MAX] = {
        89100, 89900, 91900, 99900, 107700
 };
 
-static int EmultatorIdx = 0;
-
 /*---------------------------------------------------------------------------
     LOCAL FUNCTION PROTOTYPES:
 ---------------------------------------------------------------------------*/
@@ -134,6 +132,8 @@ static bool __mmradio_set_state(mm_radio_t * radio, int new_state);
 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_set_deemphasis(mm_radio_t * radio);
 static int __mmradio_set_band_range(mm_radio_t * radio);
 static int __mmradio_get_wave_num(mm_radio_t * radio);
@@ -232,11 +232,11 @@ int _mmradio_create_radio(mm_radio_t * radio)
        radio->subs_id = 0;
        radio->local_volume = 1.0;
 
-       /* create command lock */
-       ret = pthread_mutex_init(&radio->cmd_lock, NULL);
+       /* create mutex and thread */
+       ret = __mmradio_create_thread(radio);
        if (ret) {
-               MMRADIO_LOG_ERROR("failed to create mutex");
-               return MM_ERROR_RADIO_INTERNAL;
+               MMRADIO_LOG_ERROR("failed to create threads");
+               return ret;
        }
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
@@ -368,6 +368,8 @@ int _mmradio_destroy(mm_radio_t * radio)
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
 
        _mmradio_unrealize(radio);
+       /* destroy mutex and thread */
+       __mmradio_destroy_thread(radio);
 
 #ifdef TIZEN_FEATURE_SOUND_FOCUS
        ret = mmradio_sound_focus_deregister(&radio->sound_focus);
@@ -855,20 +857,16 @@ int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
 
-       int ret = 0;
-
-       /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
-       /*      return MM_ERROR_RADIO_NOT_INITIALIZED; */
+       if (radio->seek.is_running) {
+               MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
+               return MM_ERROR_RADIO_INTERNAL;
+       }
 
        MMRADIO_SLOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d", direction);
        radio->seek_direction = direction;
-
-       ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio);
-
-       if (ret) {
-               MMRADIO_LOG_DEBUG("failed to create thread");
-               return MM_ERROR_RADIO_INTERNAL;
-       }
+       radio->seek.is_running = true;
+       radio->seek.stop = false;
+       MMRADIO_SEEK_THREAD_SIGNAL(radio);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -882,16 +880,10 @@ int _mmradio_start_scan(mm_radio_t * radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
 
-       int scan_tr_id = 0;
+       radio->scan.stop = false;
+       radio->scan.is_running = true;
 
-       radio->stop_scan = false;
-
-       scan_tr_id = pthread_create(&radio->scan_thread, NULL, (void *)__mmradio_scan_thread, (void *)radio);
-
-       if (scan_tr_id != 0) {
-               MMRADIO_LOG_DEBUG("failed to create thread : scan");
-               return MM_ERROR_RADIO_NOT_INITIALIZED;
-       }
+       MMRADIO_SCAN_THREAD_SIGNAL(radio);
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
@@ -907,12 +899,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->stop_scan = true;
-
-       if (radio->scan_thread > 0) {
-               pthread_join(radio->scan_thread, NULL);
-               radio->scan_thread = 0;
-       }
+       radio->scan.stop = true;
 
        MMRADIO_LOG_FLEAVE();
 
@@ -943,35 +930,58 @@ void __mmradio_scan_thread(mm_radio_t * radio)
 {
 
        int prev_freq = 0;
-       EmultatorIdx = 0;
+       int emulatoridx = 0;
+       int freq = 0;
 
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
-       /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
-       /*      goto FINISHED; */
 
-       if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE)
-               goto FINISHED;
+       MMRADIO_SCAN_THREAD_LOCK(radio);
 
-       if (radio->old_state == MM_RADIO_STATE_PLAYING)
-               _mmradio_mute(radio);
+       while (!radio->scan.thread_exit) {
+               MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
+               MMRADIO_SCAN_THREAD_WAIT(radio);
 
-       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
-       MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
+               if (radio->scan.thread_exit) {
+                       MMRADIO_LOG_DEBUG("exiting scan thread");
+                       goto EXIT;
+               }
 
-       while (!radio->stop_scan) {
-               int freq = 0;
-               MMMessageParamType param = { 0, };
+               if (radio->scan.stop) {
+                       MMRADIO_LOG_INFO("scan was stopped");
+                       goto FINISHED;
+               }
 
-               MMRADIO_LOG_DEBUG("scanning....");
+               if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE)
+                       goto FINISHED;
 
-               /* now we can get new frequency from radio device */
+               if (radio->old_state == MM_RADIO_STATE_PLAYING)
+                       _mmradio_mute(radio);
+
+               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
+               MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
+
+               prev_freq = 0;
+               emulatoridx = 0;
+
+               while (!radio->scan.stop) {
+
+                       MMMessageParamType param = { 0, };
+                       freq = 0;
+
+                       MMRADIO_LOG_DEBUG("scanning....");
+
+                       /* now we can get new frequency from radio device */
+                       if (radio->scan.thread_exit) {
+                               MMRADIO_LOG_DEBUG("exiting scan thread");
+                               goto EXIT;
+                       }
+
+                       if (radio->scan.stop)
+                               break;
 
-               if (radio->stop_scan)
-                       break;
-               {
                        usleep(1000 * 1000);
-                       freq = MMRadioEmulatorFreq[EmultatorIdx];
+                       freq = MMRadioEmulatorFreq[emulatoridx];
                        MMRADIO_LOG_DEBUG("freq: %d", freq);
 
                        if (freq < prev_freq) {
@@ -979,6 +989,14 @@ void __mmradio_scan_thread(mm_radio_t * radio)
                                break;
                        }
 
+                       if (radio->scan.thread_exit) {
+                               MMRADIO_LOG_DEBUG("exiting scan thread");
+                               goto EXIT;
+                       }
+
+                       if (radio->scan.stop)
+                               break;
+
                        if (freq == prev_freq)
                                continue;
 
@@ -993,32 +1011,42 @@ void __mmradio_scan_thread(mm_radio_t * radio)
                                break;
                        }
 
-                       if (radio->stop_scan)
+                       if (radio->scan.stop)
                                break;                  /* doesn't need to post */
 
                        MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
-                       EmultatorIdx++;
+                       emulatoridx++;
+                       if (emulatoridx >= EMULATOR_FREQ_MAX)
+                               break;
                }
-       }
- FINISHED:
-       radio->scan_thread = 0;
-
-       if (radio->old_state == MM_RADIO_STATE_READY) {
-               MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
-       } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
-               _mmradio_unmute(radio);
-               MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
-       }
 
-       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);
+FINISHED:
+               if (radio->old_state == MM_RADIO_STATE_READY) {
+                       MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
+               } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
+                       _mmradio_unmute(radio);
+                       MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
+                       /* check if it's limit freq or not */
+                       if (__is_tunable_frequency(radio, freq)) {
+                               /* now tune to new frequency */
+                               if (_mmradio_set_frequency(radio, freq))
+                                       MMRADIO_LOG_ERROR("failed to tune to new frequency");
+                       }
+               }
 
-       MMRADIO_LOG_FLEAVE();
+               if (!radio->scan.stop)
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
+               else
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
 
-       pthread_exit(NULL);
+               radio->scan.is_running = false;
+               radio->scan.stop = false;
+       }
 
+EXIT:
+       MMRADIO_SCAN_THREAD_UNLOCK(radio);
+       MMRADIO_LOG_FLEAVE();
+       pthread_exit(NULL);
        return;
 }
 
@@ -1038,104 +1066,100 @@ bool __is_tunable_frequency(mm_radio_t * radio, int freq)
 
 void __mmradio_seek_thread(mm_radio_t * radio)
 {
-       int ret = 0;
        int freq = 0;
-       bool seek_stop = false;
+       int i = 0;
+       int emulatoridx = 0;
        MMMessageParamType param = { 0, };
-       struct v4l2_hw_freq_seek vs = { 0, };
-
-       vs.tuner = TUNER_INDEX;
-       vs.type = V4L2_TUNER_RADIO;
-       vs.wrap_around = DEFAULT_WRAP_AROUND;
 
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       /* check direction */
-       switch (radio->seek_direction) {
-       case MM_RADIO_SEEK_UP:
-               vs.seek_upward = 1;
-               break;
-       default:
-               vs.seek_upward = 0;
-               break;
-       }
+       MMRADIO_SEEK_THREAD_LOCK(radio);
 
-       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
+       while (!radio->seek.thread_exit) {
+               MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.\n");
+               MMRADIO_SEEK_THREAD_WAIT(radio);
 
-       MMRADIO_LOG_DEBUG("seeking....");
+               if (radio->seek.thread_exit) {
+                       MMRADIO_LOG_DEBUG("exiting seek thread");
+                       break;
+               }
 
-       EmultatorIdx = 0;
-       while (!seek_stop) {
-               /* now we can get new frequency from radio device */
-               {
-                       MMRADIO_LOG_DEBUG("start radio->freq: %d", radio->freq);
-
-                       int i = 0;
-                       for (i = 0; i < EMULATOR_FREQ_MAX; i++)
-                               if (MMRadioEmulatorFreq[i] == radio->freq)
-                                       EmultatorIdx = i;
-
-                       if (vs.seek_upward == 1) {
-                               if (EmultatorIdx == EMULATOR_FREQ_MAX - 1)
-                                       EmultatorIdx = -1;
-                               freq = MMRadioEmulatorFreq[EmultatorIdx + 1];
-                       } else {
-                               if (EmultatorIdx == 0)
-                                       EmultatorIdx = EMULATOR_FREQ_MAX;
-                               freq = MMRadioEmulatorFreq[EmultatorIdx - 1];
-                       }
+               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
+               MMRADIO_LOG_DEBUG("seeking....");
 
-                       radio->freq = freq;
-                       MMRADIO_LOG_DEBUG("radio->freq: %d EmultatorIdx: %d", radio->freq, EmultatorIdx);
+               if (radio->seek.stop) {
+                       MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
+                       goto SEEK_FAILED;
                }
 
+               emulatoridx = 0;
+               MMRADIO_LOG_DEBUG("start radio->freq: %d", radio->freq);
+               freq = radio->freq;
+
+               if (radio->seek_direction == MM_RADIO_SEEK_UP) {
+                       for (i = 0; i < EMULATOR_FREQ_MAX; i++) {
+                               if (radio->freq < MMRadioEmulatorFreq[i]) {
+                                       freq = MMRadioEmulatorFreq[i];
+                                       emulatoridx = i;
+                                       break;
+                               }
+                       }
+                       if (freq == radio->freq) {
+                               freq = MMRadioEmulatorFreq[0];
+                               emulatoridx = 0;
+                       }
+               } else {
+                       for (i = EMULATOR_FREQ_MAX - 1; i < 0; i--) {
+                               if (radio->freq > MMRadioEmulatorFreq[i]) {
+                                       freq = MMRadioEmulatorFreq[i];
+                                       emulatoridx = i;
+                                       break;
+                               }
+                       }
+                       if (freq == radio->freq) {
+                               freq = MMRadioEmulatorFreq[EMULATOR_FREQ_MAX - 1];
+                               emulatoridx = EMULATOR_FREQ_MAX - 1;
+                       }
+               }
+
+               radio->freq = freq;
+               MMRADIO_LOG_DEBUG("radio->freq: %d emulatoridx: %d", radio->freq, emulatoridx);
+
                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.");
-                       continue;
+                       goto SEEK_FAILED;
                }
 
                /* check if it's limit freq or not */
                if (__is_tunable_frequency(radio, freq)) {
                        /* now tune to new frequency */
-                       ret = _mmradio_set_frequency(radio, freq);
-                       if (ret) {
+                       if (_mmradio_set_frequency(radio, freq)) {
                                MMRADIO_LOG_ERROR("failed to tune to new frequency");
                                goto SEEK_FAILED;
                        }
                }
 
-               /* 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.
-                */
-#if 0
-               ret = _mmradio_unmute(radio);
-               if (ret) {
-                       MMRADIO_LOG_ERROR("failed to tune to new frequency\n");
-                       goto SEEK_FAILED;
-               }
-#endif
                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);
-               seek_stop = true;
-       }
+               radio->seek.stop = true;
+               radio->seek.is_running = false;
+               continue;
 
-       radio->seek_thread = 0;
+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);
+               radio->seek.stop = true;
+               radio->seek.is_running = false;
+       }
 
+       MMRADIO_SEEK_THREAD_UNLOCK(radio);
        MMRADIO_LOG_FLEAVE();
-
-       pthread_exit(NULL);
-       return;
-
- 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);
        pthread_exit(NULL);
        return;
 }
@@ -1521,11 +1545,11 @@ static int __mmradio_get_wave_num(mm_radio_t * radio)
                break;
 
        case 89900:
-               val = 5;
+               val = 2;
                break;
 
        case 91900:
-               val = 6;
+               val = 5;
                break;
 
        case 99900:
@@ -1626,3 +1650,91 @@ int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
        return MM_ERROR_NONE;
 }
 
+static int __mmradio_create_thread(mm_radio_t *radio)
+{
+       int ret = MM_ERROR_NONE;
+
+       MMRADIO_LOG_FENTER();
+
+       MMRADIO_CHECK_INSTANCE(radio);
+
+       MMRADIO_INIT_MUTEX(radio->cmd_lock);
+
+       MMRADIO_INIT_MUTEX(radio->seek.mutex);
+       MMRADIO_INIT_COND(radio->seek.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_INIT_MUTEX(radio->scan.mutex);
+       MMRADIO_INIT_COND(radio->scan.cond);
+
+       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;
+       }
+
+       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->seek.mutex);
+       pthread_cond_destroy(&radio->seek.cond);
+       pthread_mutex_destroy(&radio->scan.mutex);
+       pthread_cond_destroy(&radio->scan.cond);
+
+       return MM_ERROR_RADIO_INTERNAL;
+}
+
+static void __mmradio_destroy_thread(mm_radio_t *radio)
+{
+       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 (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;
+       }
+
+       pthread_mutex_destroy(&radio->cmd_lock);
+
+       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();
+
+}
index 1e7bb92..e1f55f1 100755 (executable)
@@ -123,6 +123,8 @@ 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);
 
 #ifdef TIZEN_FEATURE_SOUND_FOCUS
 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
@@ -196,17 +198,11 @@ int _mmradio_create_radio(mm_radio_t *radio)
        memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
        radio->local_volume = 1.0;
 
-       /* create command lock */
-       ret = pthread_mutex_init(&radio->cmd_lock, NULL);
+       /* create mutex and thread */
+       ret = __mmradio_create_thread(radio);
        if (ret) {
-               MMRADIO_LOG_ERROR("failed to create mutex");
-               return MM_ERROR_RADIO_INTERNAL;
-       }
-
-       ret = pthread_mutex_init(&radio->volume_lock, NULL);
-       if (ret) {
-               MMRADIO_LOG_ERROR("failed to create volume mutex");
-               return MM_ERROR_RADIO_INTERNAL;
+               MMRADIO_LOG_ERROR("failed to create threads");
+               return ret;
        }
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
@@ -256,12 +252,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_ERROR("failed to create seek cancel mutex %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;
@@ -335,16 +325,11 @@ int _mmradio_unrealize(mm_radio_t *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);
 #endif
 
-       pthread_mutex_destroy(&radio->seek_cancel_mutex);
-
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
 
        MMRADIO_LOG_FLEAVE();
@@ -362,21 +347,15 @@ int _mmradio_destroy(mm_radio_t *radio)
 
        _mmradio_unrealize(radio);
 
+       /* destroy mutex and thread */
+       __mmradio_destroy_thread(radio);
+
        ret = radio_hal_interface_deinit(radio->hal_inf);
        if (ret) {
                MMRADIO_LOG_ERROR("failed to deinitialize radio hal interface");
                return ret;
        }
 
-       /* destroy command lock */
-       ret = pthread_mutex_destroy(&radio->cmd_lock);
-       if (ret)
-               MMRADIO_LOG_ERROR("failed to destory muxtex");
-
-       ret = pthread_mutex_destroy(&radio->volume_lock);
-       if (ret)
-               MMRADIO_LOG_ERROR("failed to destory volume mutex");
-
 #ifdef TIZEN_FEATURE_SOUND_FOCUS
        ret = mmradio_sound_focus_deregister(&radio->sound_focus);
        if (ret) {
@@ -469,7 +448,7 @@ int _mmradio_mute(mm_radio_t *radio)
                return ret;
        }
 
-       radio->is_muted = TRUE;
+       radio->is_muted = true;
        MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
        MMRADIO_LOG_FLEAVE();
 
@@ -493,7 +472,7 @@ int _mmradio_unmute(mm_radio_t *radio)
                return ret;
        }
 
-       radio->is_muted = FALSE;
+       radio->is_muted = false;
        MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
        MMRADIO_LOG_FLEAVE();
 
@@ -613,7 +592,7 @@ int _mmradio_start(mm_radio_t *radio)
                        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");
        }
@@ -661,7 +640,7 @@ error1:
        radio_hal_close(radio->hal_inf);
 error2:
        radio_hal_unprepare(radio->hal_inf);
-       radio->is_ready = FALSE;
+       radio->is_ready = false;
        return ret;
 }
 
@@ -674,7 +653,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
@@ -693,40 +671,41 @@ int _mmradio_stop(mm_radio_t *radio)
                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("failed to close radio hal");
-               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("failed to unprepare 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("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;
+                       }
 
-       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;
+                       ret = mm_resource_manager_commit(radio->resource_manager);
+                       if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
+                               MMRADIO_LOG_ERROR("resource manager commit fail");
                }
 
-               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;
        }
-
 #ifdef TIZEN_FEATURE_SOUND_FOCUS
        if (radio->sound_focus.handle > 0) {
                ret = mmradio_release_sound_focus(&radio->sound_focus);
@@ -752,14 +731,12 @@ int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
 
-       if (radio->is_seeking) {
+       if (radio->seek.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);
@@ -769,30 +746,15 @@ int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
                        MMRADIO_LOG_ERROR("failed to set radio hal mute");
                        return ret;
                }
-               radio->seek_unmute = TRUE;
+               radio->seek_unmute = true;
        }
 
        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;
 
-       ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio);
-
-       if (ret) {
-               MMRADIO_LOG_DEBUG("failed to create thread");
-               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 set radio hal mute");
-                               radio->seek_unmute = FALSE;
-                               return ret;
-                       }
-               }
-               return MM_ERROR_RADIO_INTERNAL;
-       }
+       MMRADIO_SEEK_THREAD_SIGNAL(radio);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -801,35 +763,16 @@ 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_WARNING("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
-               } else if (ret == 0) {
-                       MMRADIO_LOG_INFO("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->seek.stop = true;
+
        MMRADIO_LOG_FLEAVE();
 }
 
-
 int _mmradio_start_scan(mm_radio_t *radio)
 {
        int ret = MM_ERROR_NONE;
@@ -839,9 +782,7 @@ int _mmradio_start_scan(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
 
-       int scan_tr_id = 0;
-
-       radio->stop_scan = false;
+       radio->scan.stop = false;
 
        if (!radio->is_ready) {
                ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
@@ -878,17 +819,14 @@ int _mmradio_start_scan(mm_radio_t *radio)
                        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);
+       radio->scan.is_running = true;
 
-       if (scan_tr_id != 0) {
-               MMRADIO_LOG_ERROR("failed to create thread : scan");
-               return MM_ERROR_RADIO_NOT_INITIALIZED;
-       }
+       MMRADIO_SCAN_THREAD_SIGNAL(radio);
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
@@ -899,31 +837,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_WARNING("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
-               } else if (ret == 0) {
-                       MMRADIO_LOG_INFO("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->scan.stop = true;
 
        MMRADIO_LOG_FLEAVE();
 
@@ -962,141 +881,169 @@ void __mmradio_scan_thread(mm_radio_t *radio)
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       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);
-
-       if (ret != MM_ERROR_NONE)
-               goto FINISHED;
+       MMRADIO_SCAN_THREAD_LOCK(radio);
 
-       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
-       MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
+       while (!radio->scan.thread_exit) {
+               MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
+               MMRADIO_SCAN_THREAD_WAIT(radio);
 
-       while (!radio->stop_scan) {
-               uint32_t freq = 0;
-               MMMessageParamType param = { 0, };
-
-               MMRADIO_LOG_DEBUG("scanning....");
-
-               pthread_mutex_lock(&radio->seek_cancel_mutex);
+               if (radio->scan.thread_exit) {
+                       MMRADIO_LOG_DEBUG("exiting scan thread");
+                       goto EXIT;
+               }
 
-               if (radio->stop_scan) {
-                       MMRADIO_LOG_INFO("scan was canceled");
-                       pthread_mutex_unlock(&radio->seek_cancel_mutex);
+               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;
-               }
+               while (!radio->scan.stop) {
+                       uint32_t freq = 0;
+                       prev_freq = 0;
+                       MMMessageParamType param = { 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");
-               } 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;
+                       if (radio->scan.thread_exit) {
+                               MMRADIO_LOG_DEBUG("exiting scan thread");
+                               goto EXIT;
                        }
 
-                       prev_freq = param.radio_scan.frequency = (int)freq;
-                       MMRADIO_LOG_INFO("scanning : new frequency : [%d]", param.radio_scan.frequency);
+                       if (radio->scan.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_WARNING("%d freq is dropping...and stopping scan", 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 (radio->scan.thread_exit) {
+                               MMRADIO_LOG_DEBUG("exiting scan thread");
+                               goto EXIT;
                        }
 
-                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
+                       if (radio->scan.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 = param.radio_scan.frequency = (int)freq;
+                               MMRADIO_LOG_INFO("scanning : new frequency : [%d]", param.radio_scan.frequency);
+
+                               /* 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);
+                                       break;
+                               }
+
+                               if (radio->scan.stop) {
+                                       /* doesn't need to post */
+                                       break;
+                               }
+
+                               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
+                       }
                }
-       }
+
 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("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;
+               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 !!!! */
-               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");
-
-               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);
+               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);
                }
 
-               ret = mm_resource_manager_commit(radio->resource_manager);
-               if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
-                       MMRADIO_LOG_ERROR("resource manager commit fail");
+               if (!radio->scan.stop)
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
+               else
+                       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
+
+               radio->scan.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:
+       radio->scan.is_running = false;
+
+       MMRADIO_SCAN_THREAD_UNLOCK(radio);
 
        MMRADIO_LOG_FLEAVE();
 
-       radio->scan_thread = 0;
        pthread_exit(NULL);
+
 }
 
 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
@@ -1123,29 +1070,45 @@ void __mmradio_seek_thread(mm_radio_t *radio)
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
+       MMRADIO_SEEK_THREAD_LOCK(radio);
 
-       MMRADIO_LOG_DEBUG("seeking....");
+       while (!radio->seek.thread_exit) {
+               MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.");
+               MMRADIO_SEEK_THREAD_WAIT(radio);
 
-       if (!radio->seek_cancel) {
+               if (radio->seek.thread_exit) {
+                       MMRADIO_LOG_DEBUG("exiting seek thread");
+                       goto EXIT;
+               }
 
-               MMRADIO_LOG_DEBUG("try to seek ");
-               pthread_mutex_lock(&radio->seek_cancel_mutex);
-               MMRADIO_LOG_DEBUG("seek start");
+               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
+               MMRADIO_LOG_DEBUG("seeking....");
 
-               if (radio->seek_cancel) {
+               if (radio->seek.stop) {
                        MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
-                       pthread_mutex_unlock(&radio->seek_cancel_mutex);
                        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("failed to seek radio hal");
                        goto SEEK_FAILED;
                }
 
+               if (radio->seek.thread_exit) {
+                       MMRADIO_LOG_DEBUG("exiting seek thread");
+                       goto EXIT;
+               }
+
+               if (radio->seek.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) {
@@ -1183,37 +1146,36 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                                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_INFO("seeking : new frequency : [%d]", 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);
+               radio->seek.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 set unmute radio hal");
-               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 */
+               param.radio_scan.frequency = -1;
+               MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
+               radio->seek.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;
-       radio->seek_thread = 0;
+
+EXIT:
+       radio->seek.is_running = false;
+       MMRADIO_SEEK_THREAD_UNLOCK(radio);
+       MMRADIO_LOG_FLEAVE();
        pthread_exit(NULL);
 }
 
@@ -1506,7 +1468,7 @@ static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_t
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
        MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
 
-       mmradio_get_sound_focus_reason(focus_state, reason_for_change, TRUE, &event_source, &postMsg);
+       mmradio_get_sound_focus_reason(focus_state, reason_for_change, true, &event_source, &postMsg);
        radio->sound_focus.event_src = event_source;
 
        switch (focus_state) {
@@ -1710,3 +1672,98 @@ static int __resource_release_cb(mm_resource_manager_h rm,
 
        return FALSE;
 }
+
+static int __mmradio_create_thread(mm_radio_t *radio)
+{
+       int ret = MM_ERROR_NONE;
+
+       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);
+
+       MMRADIO_INIT_MUTEX(radio->seek.mutex);
+       MMRADIO_INIT_COND(radio->seek.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_INIT_MUTEX(radio->scan.mutex);
+       MMRADIO_INIT_COND(radio->scan.cond);
+
+       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;
+       }
+
+       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);
+
+       return MM_ERROR_RADIO_INTERNAL;
+}
+
+static void __mmradio_destroy_thread(mm_radio_t *radio)
+{
+       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 (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;
+       }
+
+       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();
+
+}