Integrating audio_interface_t struct and VOIP changes 31/37431/1 accepted/tizen/common/20150403.125556 accepted/tizen/mobile/20150404.084152 accepted/tizen/tv/20150404.082747 accepted/tizen/wearable/20150404.083209 submit/tizen/20150331.011137
authorRuchika Saxena <r.saxena@samsung.com>
Thu, 26 Mar 2015 11:43:34 +0000 (17:13 +0530)
committerRuchika Saxena <r.saxena@samsung.com>
Thu, 26 Mar 2015 11:46:11 +0000 (17:16 +0530)
Change-Id: I6f49cb5b7b35832b37e842b877748fe31d9870d3

15 files changed:
configure.ac
packaging/pulseaudio.spec
src/Makefile.am
src/modules/alsa/alsa-mixer.c
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c
src/modules/alsa/alsa-ucm.c
src/modules/alsa/alsa-util.c
src/modules/alsa/alsa-util.h
src/modules/alsa/module-alsa-sink.c
src/modules/alsa/module-alsa-source.c
src/modules/module-policy.c
src/modules/tizen-audio.h [new file with mode: 0755]
src/pulse/proplist.h
src/pulsecore/macro.h

index 6e0cf56..7d38317 100644 (file)
@@ -643,6 +643,14 @@ PKG_CHECK_MODULES(LIBJSON, [ json-c >= 0.11 ], [],
 
 PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.20 ])
 
+PKG_CHECK_MODULES(INIPARSER, iniparser)
+AC_SUBST(INIPARSER_CFLAGS)
+AC_SUBST(INIPARSER_LIBS)
+       
+PKG_CHECK_MODULES(VCONF, vconf)
+AC_SUBST(VCONF_CFLAGS)
+AC_SUBST(VCONF_LIBS)
+
 dnl use samsung policy module --------------------------------------------------------
 AC_ARG_ENABLE(samsung-policy, AC_HELP_STRING([--enable-samsung-policy], [using samsung-policy]),
 [
@@ -850,6 +858,8 @@ AS_IF([test "x$HAVE_ALSA" = "x1"],
     ],
     HAVE_ALSA_UCM=0)
 
+AC_SUBST(ASOUNDLIB_CFLAGS)
+AC_SUBST(ASOUNDLIB_LIBS)
 AC_SUBST(HAVE_ALSA)
 AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1])
 AS_IF([test "x$HAVE_ALSA" = "x1"], AC_DEFINE([HAVE_ALSA], 1, [Have ALSA?]))
index 4694999..2927978 100644 (file)
@@ -28,6 +28,7 @@ BuildRequires:    pkgconfig(gconf-2.0)
 BuildRequires:    pkgconfig(bluez)
 BuildRequires:    pkgconfig(sbc)
 BuildRequires:    pkgconfig(dbus-1)
+BuildRequires:    pkgconfig(iniparser)
 %if %{with x}
 BuildRequires:    pkgconfig(xi)
 %endif
@@ -206,7 +207,13 @@ echo "%{version}" > .tarball-version
 cp %{SOURCE1001} .
 
 %build
-export CFLAGS="%{optflags} -fno-strict-aliasing"
+export CFLAGS="%{optflags} -fno-strict-aliasing -D__TIZEN__ -D__TIZEN_BT__ -D__TIZEN_LOG__ -DTIZEN_MICRO"
+%if 0%{?sec_build_binary_debug_enable}
+export CFLAGS+=" -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS â€“DTIZEN_DEBUG_ENABLE"
+export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
+%endif
+
 export LD_AS_NEEDED=0
 NOCONFIGURE=yes ./bootstrap.sh
 %configure --prefix=%{_prefix} \
index 4f1f6c5..2e7af09 100644 (file)
@@ -2291,8 +2291,8 @@ module_rygel_media_server_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 if USE_SAMSUNG_POLICY
 module_policy_la_SOURCES = modules/module-policy.c
 module_policy_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_policy_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) $(VCONF_LIBS) libprotocol-native.la libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la
-module_policy_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) $(VCONF_CFLAGS)
+module_policy_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) $(VCONF_LIBS) $(INIPARSER_LIBS) $(ASOUNDLIB_LIBS) libprotocol-native.la libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la
+module_policy_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) $(VCONF_CFLAGS) $(INIPARSER_CFLAGS) $(ASOUNDLIB_CFLAGS)
 endif
 
 ###################################
index 99de0ec..3554c9b 100644 (file)
@@ -4280,6 +4280,9 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m,
     try_buffer_size = default_n_fragments * try_period_size;
 
     return pa_alsa_open_by_template(
+#ifdef __TIZEN__
+                              m->ucm_context.ucm->core,
+#endif
                               m->device_strings, dev_id, NULL, &try_ss,
                               &try_map, mode, &try_period_size,
                               &try_buffer_size, 0, NULL, NULL, true);
index 2bc27ff..d144227 100644 (file)
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
 #include <pulsecore/time-smoother.h>
+#ifdef __TIZEN__
+#include <pulsecore/shared.h>
+#endif
 
 #include <modules/reserve-wrap.h>
 
 #include "alsa-util.h"
 #include "alsa-sink.h"
 
+#ifdef __TIZEN__
+#include "tizen-audio.h"
+#endif
+
 #define ALSA_SUSPEND_ON_IDLE_TIMEOUT   "0"
 /* #define DEBUG_TIMING */
 
 #define DEFAULT_REWIND_SAFEGUARD_BYTES (1024U) /* increase safeguard 4x */
 #define DEFAULT_REWIND_SAFEGUARD_USEC (5000) /* increase safeguard ~4x */
 
+#ifdef __TIZEN__
+#define VOIP_MIN_WB_PERIOD_BYTES 640
+#define VOIP_MIN_NB_PERIOD_BYTES 320
+#define VOIP_WIDE_BAND 16000
+#endif
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -163,6 +176,10 @@ struct userdata {
 
     /* ucm context */
     pa_alsa_ucm_mapping_context *ucm_context;
+#ifdef __TIZEN__
+    /* Start threshold */
+    int start_threshold;
+#endif
 };
 
 static void userdata_free(struct userdata *u);
@@ -733,6 +750,15 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, bool polled, bo
 
         left_to_play = check_left_to_play(u, n_bytes, on_timeout);
         on_timeout = false;
+#ifdef __TIZEN__
+        if (pa_alsa_pcm_is_voip(u->pcm_handle))
+        {
+            size_t actual_n_bytes;
+            actual_n_bytes = (u->sink->sample_spec.rate == VOIP_WIDE_BAND) ? VOIP_MIN_WB_PERIOD_BYTES :VOIP_MIN_NB_PERIOD_BYTES;
+            if(n_bytes > actual_n_bytes)
+               n_bytes = actual_n_bytes;
+        }
+#endif
 
         if (u->use_tsched)
 
@@ -831,6 +857,10 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, bool polled, bo
 
             n_bytes -= written;
         }
+#ifdef __TIZEN__
+        if (pa_alsa_pcm_is_voip(u->pcm_handle))
+            break;
+#endif
     }
 
     input_underrun = pa_sink_process_input_underruns(u->sink, left_to_play);
@@ -934,6 +964,11 @@ static int build_pollfd(struct userdata *u) {
 
 /* Called from IO context */
 static int suspend(struct userdata *u) {
+#ifdef __TIZEN__
+    void *audio_data = pa_shared_get(u->core, "tizen-audio-data");
+    audio_interface_t *audio_intf = pa_shared_get(u->core, "tizen-audio-interface");
+#endif
+
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
@@ -941,6 +976,11 @@ static int suspend(struct userdata *u) {
 
     /* Let's suspend -- we don't call snd_pcm_drain() here since that might
      * take awfully long with our long buffer sizes today. */
+#ifdef __TIZEN__
+    if (audio_intf && audio_intf->alsa_pcm_close) {
+        audio_intf->alsa_pcm_close(audio_data, u->pcm_handle);
+    } else
+#endif
     snd_pcm_close(u->pcm_handle);
     u->pcm_handle = NULL;
 
@@ -1008,10 +1048,17 @@ static int update_sw_params(struct userdata *u) {
 
     pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
 
+#ifdef __TIZEN__
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min, !u->use_tsched, u->start_threshold,u->sink->sample_spec.rate)) < 0) {
+        pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err));
+        return err;
+    }
+#else
     if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min, !u->use_tsched)) < 0) {
         pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err));
         return err;
     }
+#endif
 
     pa_sink_set_max_request_within_thread(u->sink, u->hwbuf_size - u->hwbuf_unused);
      if (pa_alsa_pcm_is_hw(u->pcm_handle))
@@ -1065,6 +1112,12 @@ static int unsuspend(struct userdata *u) {
     bool b, d;
     snd_pcm_uframes_t period_size, buffer_size;
     char *device_name = NULL;
+#ifdef __TIZEN__
+    int ret = 0;
+    int hdmi_ch_enum_val = 0;
+    void *audio_data = pa_shared_get(u->core, "tizen-audio-data");
+    audio_interface_t *audio_intf = pa_shared_get(u->core, "tizen-audio-interface");
+#endif
 
     pa_assert(u);
     pa_assert(!u->pcm_handle);
@@ -1079,6 +1132,17 @@ static int unsuspend(struct userdata *u) {
         pa_snprintf(device_name, len, "%s,AES0=6", u->device_name);
     }
 
+#ifdef __TIZEN__
+    if (audio_intf && audio_intf->alsa_pcm_open) {
+        audio_return_t audio_ret = AUDIO_RET_OK;
+
+        if (AUDIO_IS_ERROR((audio_ret = audio_intf->alsa_pcm_open(audio_data, (void **)&u->pcm_handle, device_name ? device_name : u->device_name, AUDIO_DIRECTION_OUT,
+            SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT)))) {
+            pa_log("Error opening PCM device %s: %x", u->device_name, audio_ret);
+            goto fail;
+        }
+    } else
+#endif
     if ((err = snd_pcm_open(&u->pcm_handle, device_name ? device_name : u->device_name, SND_PCM_STREAM_PLAYBACK,
                             SND_PCM_NONBLOCK|
                             SND_PCM_NO_AUTO_RESAMPLE|
@@ -1094,6 +1158,13 @@ static int unsuspend(struct userdata *u) {
     b = u->use_mmap;
     d = u->use_tsched;
 
+#ifdef __TIZEN__
+    if (pa_streq (u->device_name, "hw:0,1")) {
+        hdmi_ch_enum_val = ss.channels - 2;
+        ret = pa_alsa_set_mixer_control("HDMI_RX Channels", hdmi_ch_enum_val);
+        pa_log_warn("This is HDMI(%s) device, set channelinfo(%d) mixer, ret=%d", u->device_name, hdmi_ch_enum_val, ret);
+    }
+#endif
     if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, true)) < 0) {
         pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
         goto fail;
@@ -1142,6 +1213,11 @@ static int unsuspend(struct userdata *u) {
 
 fail:
     if (u->pcm_handle) {
+#ifdef __TIZEN__
+        if (audio_intf && audio_intf->alsa_pcm_close) {
+            audio_intf->alsa_pcm_close(audio_data, u->pcm_handle);
+        } else
+#endif
         snd_pcm_close(u->pcm_handle);
         u->pcm_handle = NULL;
     }
@@ -1733,6 +1809,9 @@ static void thread_func(void *userdata) {
 
                 if (u->first) {
                     pa_log_info("Starting playback.");
+#ifdef __TIZEN__
+                    if (SND_PCM_STATE_PREPARED == snd_pcm_state(u->pcm_handle))
+#endif
                     snd_pcm_start(u->pcm_handle);
 
                     pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
@@ -2022,6 +2101,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     pa_sink_new_data data;
     pa_alsa_profile_set *profile_set = NULL;
     void *state = NULL;
+#ifdef __TIZEN__
+    int start_threshold;
+#endif
 
     pa_assert(m);
     pa_assert(ma);
@@ -2077,6 +2159,13 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     buffer_frames = buffer_size/frame_size;
     tsched_frames = tsched_size/frame_size;
 
+#ifdef __TIZEN__
+    if(pa_modargs_get_value_s32(ma, "start_threshold", &start_threshold) < 0){
+       pa_log("Failed to parse start_threshold argument.");
+       goto fail;
+    }
+#endif
+
     if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
         pa_log("Failed to parse mmap argument.");
         goto fail;
@@ -2167,6 +2256,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
         }
 
         if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
+#ifdef __TIZEN__
+                      u->core,
+#endif
                       dev_id,
                       &u->device_name,
                       &ss, &map,
@@ -2181,6 +2273,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
             goto fail;
 
         if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto(
+#ifdef __TIZEN__
+                      u->core,
+#endif
                       dev_id,
                       &u->device_name,
                       &ss, &map,
@@ -2192,6 +2287,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     } else {
 
         if (!(u->pcm_handle = pa_alsa_open_by_device_string(
+#ifdef __TIZEN__
+                      u->core,
+#endif
                       pa_modargs_get_value(ma, "device", DEFAULT_DEVICE),
                       &u->device_name,
                       &ss, &map,
@@ -2366,6 +2464,11 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
 
     reserve_update(u);
 
+#ifdef __TIZEN__
+    /*Set start Threshold*/
+    u->start_threshold = start_threshold;
+#endif
+
     if (update_sw_params(u) < 0)
         goto fail;
 
@@ -2444,6 +2547,11 @@ fail:
 }
 
 static void userdata_free(struct userdata *u) {
+#ifdef __TIZEN__
+    void *audio_data = pa_shared_get(u->core, "tizen-audio-data");
+    audio_interface_t *audio_intf = pa_shared_get(u->core, "tizen-audio-interface");
+#endif
+
     pa_assert(u);
 
     if (u->sink)
@@ -2473,6 +2581,11 @@ static void userdata_free(struct userdata *u) {
 
     if (u->pcm_handle) {
         snd_pcm_drop(u->pcm_handle);
+#ifdef __TIZEN__
+        if (audio_intf && audio_intf->alsa_pcm_close) {
+            audio_intf->alsa_pcm_close(audio_data, u->pcm_handle);
+        } else
+#endif
         snd_pcm_close(u->pcm_handle);
     }
 
index e181a30..05b25a4 100644 (file)
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
 #include <pulsecore/time-smoother.h>
+#ifdef __TIZEN__
+#include <pulsecore/shared.h>
+#endif
 
 #include <modules/reserve-wrap.h>
 
 #include "alsa-util.h"
 #include "alsa-source.h"
 
+#ifdef __TIZEN__
+#include "tizen-audio.h"
+#endif
+
 /* #define DEBUG_TIMING */
 
 #define DEFAULT_DEVICE "default"
 #define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC)               /* 200ms */
 
 #define VOLUME_ACCURACY (PA_VOLUME_NORM/100)
-
+#ifdef __TIZEN__
+#define VOIP_MIN_WB_PERIOD_BYTES 640
+#define VOIP_MIN_NB_PERIOD_BYTES 320
+#define VOIP_WIDE_BAND 16000
+#endif
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -141,6 +152,10 @@ struct userdata {
 
     /* ucm context */
     pa_alsa_ucm_mapping_context *ucm_context;
+#ifdef __TIZEN__
+    /* Start threshold */
+    int start_threshold;
+#endif
 };
 
 static void userdata_free(struct userdata *u);
@@ -665,6 +680,16 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, bool polled, boo
         }
 
         n_bytes = (size_t) n * u->frame_size;
+
+#ifdef __TIZEN__
+        if (pa_alsa_pcm_is_voip(u->pcm_handle))
+        {
+            size_t actual_n_bytes;
+            actual_n_bytes = (u->source->sample_spec.rate == VOIP_WIDE_BAND) ? VOIP_MIN_WB_PERIOD_BYTES :VOIP_MIN_NB_PERIOD_BYTES;
+            if(n_bytes > actual_n_bytes)
+               n_bytes = actual_n_bytes;
+        }
+#endif
         left_to_record = check_left_to_record(u, n_bytes, on_timeout);
         on_timeout = false;
 
@@ -839,12 +864,22 @@ static int build_pollfd(struct userdata *u) {
 
 /* Called from IO context */
 static int suspend(struct userdata *u) {
+#ifdef __TIZEN__
+    void *audio_data = pa_shared_get(u->core, "tizen-audio-data");
+    audio_interface_t *audio_intf = pa_shared_get(u->core, "tizen-audio-interface");
+#endif
+
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
     pa_smoother_pause(u->smoother, pa_rtclock_now());
 
     /* Let's suspend */
+#ifdef __TIZEN__
+    if (audio_intf && audio_intf->alsa_pcm_close) {
+        audio_intf->alsa_pcm_close(audio_data, u->pcm_handle);
+    } else
+#endif
     snd_pcm_close(u->pcm_handle);
     u->pcm_handle = NULL;
 
@@ -903,10 +938,17 @@ static int update_sw_params(struct userdata *u) {
 
     pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
 
+#ifdef __TIZEN__
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min, !u->use_tsched, u->start_threshold,u->source->sample_spec.rate)) < 0) {
+        pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err));
+        return err;
+    }
+#else
     if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min, !u->use_tsched)) < 0) {
         pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err));
         return err;
     }
+#endif
 
     return 0;
 }
@@ -951,12 +993,27 @@ static int unsuspend(struct userdata *u) {
     int err;
     bool b, d;
     snd_pcm_uframes_t period_size, buffer_size;
+#ifdef __TIZEN__
+    void *audio_data = pa_shared_get(u->core, "tizen-audio-data");
+    audio_interface_t *audio_intf = pa_shared_get(u->core, "tizen-audio-interface");
+#endif
 
     pa_assert(u);
     pa_assert(!u->pcm_handle);
 
     pa_log_info("Trying resume...");
 
+#ifdef __TIZEN__
+    if (audio_intf && audio_intf->alsa_pcm_open) {
+        audio_return_t audio_ret = AUDIO_RET_OK;
+
+        if (AUDIO_IS_ERROR((audio_ret = audio_intf->alsa_pcm_open(audio_data, (void **)&u->pcm_handle, u->device_name, AUDIO_DIRECTION_IN,
+            SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT)))) {
+            pa_log("Error opening PCM device %s: %x", u->device_name, audio_ret);
+            goto fail;
+        }
+    } else
+#endif
     if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE,
                             SND_PCM_NONBLOCK|
                             SND_PCM_NO_AUTO_RESAMPLE|
@@ -1020,6 +1077,11 @@ static int unsuspend(struct userdata *u) {
 
 fail:
     if (u->pcm_handle) {
+#ifdef __TIZEN__
+        if (audio_intf && audio_intf->alsa_pcm_close) {
+            audio_intf->alsa_pcm_close(audio_data, u->pcm_handle);
+        } else
+#endif
         snd_pcm_close(u->pcm_handle);
         u->pcm_handle = NULL;
     }
@@ -1457,6 +1519,9 @@ static void thread_func(void *userdata) {
 
             if (u->first) {
                 pa_log_info("Starting capture.");
+#ifdef __TIZEN__
+                if (SND_PCM_STATE_PREPARED == snd_pcm_state(u->pcm_handle))
+#endif
                 snd_pcm_start(u->pcm_handle);
 
                 pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
@@ -1733,6 +1798,9 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     pa_source_new_data data;
     pa_alsa_profile_set *profile_set = NULL;
     void *state = NULL;
+#ifdef __TIZEN__
+    int start_threshold;
+#endif
 
     pa_assert(m);
     pa_assert(ma);
@@ -1788,6 +1856,13 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     buffer_frames = buffer_size/frame_size;
     tsched_frames = tsched_size/frame_size;
 
+#ifdef __TIZEN__
+    if(pa_modargs_get_value_s32(ma, "start_threshold", &start_threshold) < 0){
+       pa_log("Failed to parse start_threshold argument.");
+       goto fail;
+    }
+#endif
+
     if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
         pa_log("Failed to parse mmap argument.");
         goto fail;
@@ -1871,6 +1946,9 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
         }
 
         if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
+#ifdef __TIZEN__
+                      u->core,
+#endif
                       dev_id,
                       &u->device_name,
                       &ss, &map,
@@ -1885,6 +1963,9 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
             goto fail;
 
         if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto(
+#ifdef __TIZEN__
+                      u->core,
+#endif
                       dev_id,
                       &u->device_name,
                       &ss, &map,
@@ -1896,6 +1977,9 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     } else {
 
         if (!(u->pcm_handle = pa_alsa_open_by_device_string(
+#ifdef __TIZEN__
+                      u->core,
+ #endif
                       pa_modargs_get_value(ma, "device", DEFAULT_DEVICE),
                       &u->device_name,
                       &ss, &map,
@@ -2055,6 +2139,11 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
 
     reserve_update(u);
 
+#ifdef __TIZEN__
+    /*Set start Threshold*/
+    u->start_threshold = start_threshold;
+#endif
+
     if (update_sw_params(u) < 0)
         goto fail;
 
@@ -2118,6 +2207,11 @@ fail:
 }
 
 static void userdata_free(struct userdata *u) {
+#ifdef __TIZEN__
+    void *audio_data = pa_shared_get(u->core, "tizen-audio-data");
+    audio_interface_t *audio_intf = pa_shared_get(u->core, "tizen-audio-interface");
+#endif
+
     pa_assert(u);
 
     if (u->source)
@@ -2144,6 +2238,11 @@ static void userdata_free(struct userdata *u) {
 
     if (u->pcm_handle) {
         snd_pcm_drop(u->pcm_handle);
+#ifdef __TIZEN__
+        if (audio_intf && audio_intf->alsa_pcm_close) {
+            audio_intf->alsa_pcm_close(audio_data, u->pcm_handle);
+        } else
+#endif
         snd_pcm_close(u->pcm_handle);
     }
 
index 23522c7..9d6f9ea 100644 (file)
@@ -1387,7 +1387,11 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m,
         pa_frame_size(&try_ss);
     try_buffer_size = ucm->core->default_n_fragments * try_period_size;
 
-    pcm = pa_alsa_open_by_device_string(m->device_strings[0], NULL, &try_ss,
+    pcm = pa_alsa_open_by_device_string(
+#ifdef __TIZEN__
+            ucm->core,
+#endif
+           m->device_strings[0], NULL, &try_ss,
             &try_map, mode, &try_period_size, &try_buffer_size, 0, NULL, NULL, exact_channels);
 
     if (pcm && !exact_channels)
index 73b1332..7865303 100644 (file)
@@ -42,6 +42,9 @@
 #include <pulsecore/thread.h>
 #include <pulsecore/conf-parser.h>
 #include <pulsecore/core-rtclock.h>
+#ifdef __TIZEN__
+#include <pulsecore/shared.h>
+#endif
 
 #include "alsa-util.h"
 #include "alsa-mixer.h"
 #include "udev-util.h"
 #endif
 
+#ifdef __TIZEN__
+#include "tizen-audio.h"
+#endif
+
 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
 
     static const snd_pcm_format_t format_trans[] = {
@@ -432,13 +439,37 @@ finish:
     return ret;
 }
 
+#ifdef __TIZEN__
+    // FIXME : Fix added for VT avsync issue + Reducing voip HW buff size
+#define VOIP_WIDE_BAND 16000
+#define VOIP_WB_AVAIL_MIN 160
+#define VOIP_NB_AVAIL_MIN 80
+#endif
+
+#ifdef __TIZEN__
+int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event, int start_threshold,int sampling_rate) {
+#else
 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event) {
+#endif
     snd_pcm_sw_params_t *swparams;
     snd_pcm_uframes_t boundary;
     int err;
+#ifdef __TIZEN__
+    snd_pcm_uframes_t stop_threshold = 0;
+#endif
 
     pa_assert(pcm);
 
+#ifdef __TIZEN__
+    if (start_threshold > 0) {
+        avail_min = start_threshold;
+    }
+
+    if (pa_alsa_pcm_is_voip(pcm)) {
+    // FIXME : Fix added for VT avsync issue + Reducing voip HW buff size
+        avail_min = (sampling_rate == VOIP_WIDE_BAND) ? VOIP_WB_AVAIL_MIN :VOIP_NB_AVAIL_MIN;
+    }
+#endif
     snd_pcm_sw_params_alloca(&swparams);
 
     if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
@@ -461,6 +492,17 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool peri
         return err;
     }
 
+#ifdef __TIZEN__
+    if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, (stop_threshold)? stop_threshold:boundary)) < 0) {
+        pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
+        return err;
+    }
+
+    if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (start_threshold > 0)? (snd_pcm_uframes_t)start_threshold : avail_min)) < 0) {
+        pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
+        return err;
+    }
+#else
     if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
         pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
         return err;
@@ -470,6 +512,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool peri
         pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
         return err;
     }
+#endif
 
     if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
         pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
@@ -485,6 +528,9 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool peri
 }
 
 snd_pcm_t *pa_alsa_open_by_device_id_auto(
+#ifdef __TIZEN__
+        pa_core *c,
+#endif
         const char *dev_id,
         char **dev,
         pa_sample_spec *ss,
@@ -523,6 +569,9 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
         pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
 
         pcm_handle = pa_alsa_open_by_device_id_mapping(
+#ifdef __TIZEN__
+                c,
+#endif
                 dev_id,
                 dev,
                 ss,
@@ -550,6 +599,9 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
         pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
 
         pcm_handle = pa_alsa_open_by_device_id_mapping(
+#ifdef __TIZEN__
+                c,
+#endif
                 dev_id,
                 dev,
                 ss,
@@ -574,6 +626,9 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
     d = pa_sprintf_malloc("hw:%s", dev_id);
     pa_log_debug("Trying %s as last resort...", d);
     pcm_handle = pa_alsa_open_by_device_string(
+#ifdef __TIZEN__
+            c,
+#endif
             d,
             dev,
             ss,
@@ -594,6 +649,9 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
 }
 
 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
+#ifdef __TIZEN__
+        pa_core *c,
+#endif
         const char *dev_id,
         char **dev,
         pa_sample_spec *ss,
@@ -622,6 +680,9 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
     try_map = m->channel_map;
 
     pcm_handle = pa_alsa_open_by_template(
+#ifdef __TIZEN__
+            c,
+#endif
             m->device_strings,
             dev_id,
             dev,
@@ -646,6 +707,9 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
 }
 
 snd_pcm_t *pa_alsa_open_by_device_string(
+#ifdef __TIZEN__
+        pa_core *c,
+#endif
         const char *device,
         char **dev,
         pa_sample_spec *ss,
@@ -662,6 +726,12 @@ snd_pcm_t *pa_alsa_open_by_device_string(
     char *d;
     snd_pcm_t *pcm_handle;
     bool reformat = false;
+#ifdef __TIZEN__
+    int ret = 0;
+    int hdmi_ch_enum_val = 0;
+    void *audio_data = NULL;
+    audio_interface_t *audio_intf = NULL;
+#endif
 
     pa_assert(device);
     pa_assert(ss);
@@ -672,6 +742,19 @@ snd_pcm_t *pa_alsa_open_by_device_string(
     for (;;) {
         pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
 
+#ifdef __TIZEN__
+        audio_data = pa_shared_get(c, "tizen-audio-data");
+        audio_intf = pa_shared_get(c, "tizen-audio-interface");
+        if (audio_intf && audio_intf->alsa_pcm_open) {
+            audio_return_t audio_ret = AUDIO_RET_OK;
+
+            if (AUDIO_IS_ERROR((audio_ret = audio_intf->alsa_pcm_open(audio_data, (void **)&pcm_handle, d, (mode == SND_PCM_STREAM_PLAYBACK) ? AUDIO_DIRECTION_OUT : AUDIO_DIRECTION_IN,
+                SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))))) {
+                pa_log("Error opening PCM device %s: %x", d, audio_ret);
+                goto fail;
+            }
+        } else
+#endif
         if ((err = snd_pcm_open(&pcm_handle, d, mode,
                                 SND_PCM_NONBLOCK|
                                 SND_PCM_NO_AUTO_RESAMPLE|
@@ -696,6 +779,11 @@ snd_pcm_t *pa_alsa_open_by_device_string(
             if (!reformat) {
                 reformat = true;
 
+#ifdef __TIZEN__
+                if (audio_data && audio_intf && audio_intf->alsa_pcm_close) {
+                    audio_intf->alsa_pcm_close(audio_data, pcm_handle);
+                } else
+#endif
                 snd_pcm_close(pcm_handle);
                 continue;
             }
@@ -710,11 +798,21 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 
                 reformat = false;
 
+#ifdef __TIZEN__
+                if (audio_data && audio_intf && audio_intf->alsa_pcm_close) {
+                    audio_intf->alsa_pcm_close(audio_data, pcm_handle);
+                } else
+#endif
                 snd_pcm_close(pcm_handle);
                 continue;
             }
 
             pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
+#ifdef __TIZEN__
+            if (audio_data && audio_intf && audio_intf->alsa_pcm_close) {
+                audio_intf->alsa_pcm_close(audio_data, pcm_handle);
+            } else
+#endif
             snd_pcm_close(pcm_handle);
 
             goto fail;
@@ -738,6 +836,9 @@ fail:
 }
 
 snd_pcm_t *pa_alsa_open_by_template(
+#ifdef __TIZEN__
+        pa_core *c,
+#endif
         char **template,
         const char *dev_id,
         char **dev,
@@ -760,6 +861,9 @@ snd_pcm_t *pa_alsa_open_by_template(
         d = pa_replace(*i, "%f", dev_id);
 
         pcm_handle = pa_alsa_open_by_device_string(
+#ifdef __TIZEN__
+                c,
+#endif
                 d,
                 dev,
                 ss,
@@ -1407,6 +1511,27 @@ bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
     return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
 }
 
+#ifdef __TIZEN__
+pa_bool_t pa_alsa_pcm_is_voip(snd_pcm_t *pcm) {
+    char *id = NULL;
+    snd_pcm_info_t* info;
+    snd_pcm_info_alloca(&info);
+
+    pa_assert(pcm);
+
+    if (snd_pcm_info(pcm, info) < 0)
+        return false;
+
+    if (!(id = snd_pcm_info_get_id(info)))
+        return false;
+
+    if(!strncmp(id, "VoIP",4))
+        return true;
+
+    return false;
+}
+#endif
+
 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
 
 const char* pa_alsa_strerror(int errnum) {
@@ -1646,3 +1771,89 @@ int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
 
     return 0;
 }
+
+#ifdef __TIZEN__
+int pa_alsa_set_mixer_control(const char *ctl_name, int val)
+{
+    snd_ctl_t *handle;
+    snd_ctl_elem_value_t *control;
+    snd_ctl_elem_id_t *id;
+    snd_ctl_elem_info_t *info;
+    snd_ctl_elem_type_t type;
+
+    char *card_name = NULL;
+    int ret = 0, count = 0, i = 0;
+
+    snd_card_get_name(0, &card_name);
+    if(!card_name)
+        card_name = strdup("default");
+
+    ret = snd_ctl_open(&handle, card_name, 0);
+    if (ret < 0) {
+        pa_log_error("snd_ctl_open error, card: %s: %s", card_name, snd_strerror(ret));
+        if (card_name != NULL) {
+            free(card_name);
+            card_name = NULL;
+        }
+        return -1;
+    }
+    if (card_name != NULL) {
+        free(card_name);
+        card_name = NULL;
+    }
+    // Get Element Info
+
+    snd_ctl_elem_id_alloca(&id);
+    snd_ctl_elem_info_alloca(&info);
+    snd_ctl_elem_value_alloca(&control);
+
+    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
+    snd_ctl_elem_id_set_name(id, ctl_name);
+
+    snd_ctl_elem_info_set_id(info, id);
+    if(snd_ctl_elem_info(handle, info) < 0 ) {
+        pa_log_error("Cannot find control element: %s", ctl_name);
+        goto close;
+    }
+    snd_ctl_elem_info_get_id(info, id);
+
+    type = snd_ctl_elem_info_get_type(info);
+    count = snd_ctl_elem_info_get_count(info);
+
+    snd_ctl_elem_value_set_id(control, id);
+
+    snd_ctl_elem_read(handle, control);
+
+    pa_log_debug("type(%d), count(%d): ", type, count);
+
+    switch (type) {
+    case SND_CTL_ELEM_TYPE_BOOLEAN:
+        for (i = 0; i < count; i++)
+            snd_ctl_elem_value_set_boolean(control, i, val);
+        break;
+    case SND_CTL_ELEM_TYPE_INTEGER:
+        for (i = 0; i < count; i++)
+            snd_ctl_elem_value_set_integer(control, i,val);
+        break;
+    case SND_CTL_ELEM_TYPE_ENUMERATED:
+        for (i = 0; i < count; i++)
+            snd_ctl_elem_value_set_enumerated(control, i,val);
+        break;
+
+    default:
+        pa_log_warn("unsupported control element type");
+        goto close;
+    }
+
+    snd_ctl_elem_write(handle, control);
+
+    snd_ctl_close(handle);
+
+    return 0;
+
+close:
+    pa_log_error("Error");
+    snd_ctl_close(handle);
+    return -1;
+}
+#endif
index 0e3ae69..bcdf26c 100644 (file)
@@ -45,13 +45,25 @@ int pa_alsa_set_hw_params(
         bool *use_tsched,                  /* modified at return */
         bool require_exact_channel_number);
 
+#ifdef __TIZEN__
+int pa_alsa_set_sw_params(
+        snd_pcm_t *pcm,
+        snd_pcm_uframes_t avail_min,
+        bool period_event,
+        int start_threshold,
+        int sampling_rate );
+#else
 int pa_alsa_set_sw_params(
         snd_pcm_t *pcm,
         snd_pcm_uframes_t avail_min,
         bool period_event);
+#endif
 
 /* Picks a working mapping from the profile set based on the specified ss/map */
 snd_pcm_t *pa_alsa_open_by_device_id_auto(
+#ifdef __TIZEN__
+        pa_core *c,
+#endif
         const char *dev_id,
         char **dev,                       /* modified at return */
         pa_sample_spec *ss,               /* modified at return */
@@ -67,6 +79,9 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
 
 /* Uses the specified mapping */
 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
+#ifdef __TIZEN__
+        pa_core *c,
+#endif
         const char *dev_id,
         char **dev,                       /* modified at return */
         pa_sample_spec *ss,               /* modified at return */
@@ -81,6 +96,9 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
 
 /* Opens the explicit ALSA device */
 snd_pcm_t *pa_alsa_open_by_device_string(
+#ifdef __TIZEN__
+        pa_core *c,
+#endif
         const char *dir,
         char **dev,                       /* modified at return */
         pa_sample_spec *ss,               /* modified at return */
@@ -95,6 +113,9 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 
 /* Opens the explicit ALSA device with a fallback list */
 snd_pcm_t *pa_alsa_open_by_template(
+#ifdef __TIZEN__
+        pa_core *c,
+#endif
         char **template,
         const char *dev_id,
         char **dev,                       /* modified at return */
@@ -137,6 +158,9 @@ unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_
 
 bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm);
 bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm);
+#ifdef __TIZEN__
+pa_bool_t pa_alsa_pcm_is_voip(snd_pcm_t *pcm);
+#endif
 
 const char* pa_alsa_strerror(int errnum);
 
@@ -154,4 +178,8 @@ struct pa_hdmi_eld {
 
 int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld);
 
+#ifdef __TIZEN__
+int pa_alsa_set_mixer_control(const char *ctl_name, int val);
+#endif
+
 #endif
index fdcb5cf..a9ffa90 100644 (file)
@@ -87,6 +87,9 @@ static const char* const valid_modargs[] = {
     "deferred_volume_safety_margin",
     "deferred_volume_extra_delay",
     "fixed_latency_range",
+#ifdef __TIZEN__
+    "start_threshold",
+#endif
     NULL
 };
 
index 7c8ace4..82dbccd 100644 (file)
@@ -94,6 +94,9 @@ static const char* const valid_modargs[] = {
     "deferred_volume_safety_margin",
     "deferred_volume_extra_delay",
     "fixed_latency_range",
+#ifdef __TIZEN__
+    "start_threshold",
+#endif
     NULL
 };
 
index 2172018..c713497 100644 (file)
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+#include <strings.h>
+#include <vconf.h> // for mono
+#include <iniparser.h>
+#include <dlfcn.h>
+#include <asoundlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include <pulse/proplist.h>
+#include <pulse/timeval.h>
+#include <pulse/util.h>
+#include <pulse/rtclock.h>
+
 #include <pulsecore/core.h>
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
+#include <pulsecore/core-error.h>
 #include <pulsecore/core-rtclock.h>
+#include <pulsecore/core-scache.h>
+#include <pulsecore/core-subscribe.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/mutex.h>
 #include <pulsecore/log.h>
-#include <stdbool.h>
-#include <strings.h>
-
-#include <pulsecore/log.h>
-#include <pulsecore/core-subscribe.h>
+#include <pulsecore/namereg.h>
 #include <pulsecore/sink-input.h>
 #include <pulsecore/source-output.h>
-#include <pulsecore/namereg.h>
-#include <pulsecore/core-error.h>
-
 #include <pulsecore/protocol-native.h>
 #include <pulsecore/pstream-util.h>
-#include <vconf.h> // for mono
+#include <pulsecore/strbuf.h>
+#include <pulsecore/sink-input.h>
+#include <pulsecore/sound-file.h>
+#include <pulsecore/play-memblockq.h>
+#include <pulsecore/shared.h>
 
 #include "module-policy-symdef.h"
+#include "tizen-audio.h"
+
+#define VCONFKEY_SOUND_HDMI_SUPPORT "memory/private/sound/hdmisupport"
+#ifdef PRIMARY_VOLUME
+#define VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE "memory/private/sound/PrimaryVolumetype"
+#endif
+
+//To be changed
+#define VCONFKEY_SOUND_CAPTURE_STATUS "memory/private/sound/CaptureStatus"
+#define VCONFKEY_CALL_NOISE_REDUCTION_STATE_BOOL "memory/private/call/NoiseReduction"
+#define VCONFKEY_CALL_EXTRA_VOLUME_STATE_BOOL "memory/private/call/ExtraVolume"
+#define VCONFKEY_CALL_WBAMR_STATE_BOOL "memory/private/call/WBAMRState"
+
+
 
 PA_MODULE_AUTHOR("Seungbae Shin");
 PA_MODULE_DESCRIPTION("Media Policy module");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(true);
 PA_MODULE_USAGE(
-        "on_hotplug=<When new device becomes available, recheck streams?> ");
+        "on_hotplug=<When new device becomes available, recheck streams?> "
+        "use_wideband_voice=<Set to 1 to enable wb voice. Default nb>"
+        "fragment_size=<fragment size>"
+        "tsched_buffer_size=<buffer size when using timer based scheduling> ");
 
 static const char* const valid_modargs[] = {
     "on_hotplug",
+    "use_wideband_voice",
+    "fragment_size",
+    "tsched_buffersize",
+    "tsched_buffer_size",
     NULL
 };
 
+/* Audio HAL library */
+#define LIB_TIZEN_AUDIO "libtizen-audio.so"
+
+/* Tunning Value */
+#define DEFAULT_TSCHED_BUFFER_SIZE 16384
+#define START_THRESHOLD    4096
+#ifdef TIZEN_MICRO
+#define DEFAULT_FRAGMENT_SIZE 4096
+#else
+#define DEFAULT_FRAGMENT_SIZE 8192
+#endif
+
+/* Sink & Source names */
+#define AEC_SINK            "alsa_output.0.analog-stereo.echo-cancel"
+#define AEC_SOURCE          "alsa_input.0.analog-stereo.echo-cancel"
+#define SINK_VOIP           "alsa_output.3.analog-stereo"
+#define SINK_VIRTUAL        "alsa_output.virtual.analog-stereo"
+#define ALSA_VIRTUAL_CARD   "VIRTUALAUDIO"
+#define SOURCE_ALSA         "alsa_input.0.analog-stereo"
+#define SOURCE_VIRTUAL      "alsa_input.virtual.analog-stereo"
+#define SOURCE_VOIP         "alsa_input.3.analog-stereo"
+#define SINK_ALSA           "alsa_output.0.analog-stereo"
+#define SINK_ALSA_UHQA      "alsa_output.0.analog-stereo-uhqa"
+#define SINK_COMBINED       "combined"
+#define SINK_MONO_ALSA         "mono_alsa"
+#define SINK_MONO_BT           "mono_bt"
+#define SINK_MONO_COMBINED     "mono_combined"
+#define SINK_HIGH_LATENCY   "alsa_output.4.analog-stereo"
+#define SINK_HIGH_LATENCY_UHQA   "alsa_output.4.analog-stereo-uhqa"
+#define SINK_HDMI           "alsa_output.1.analog-stereo"
+#define SINK_HDMI_UHQA           "alsa_output.1.analog-stereo-uhqa"
+#define SOURCE_MIRRORING    "alsa_input.8.analog-stereo"
+#define ALSA_MONITOR_SOURCE "alsa_output.0.analog-stereo.monitor"
+
+
+/* Policies */
+#define POLICY_AUTO         "auto"
+#define POLICY_AUTO_UHQA    "auto-uhqa"
+#define POLICY_PHONE        "phone"
+#define POLICY_ALL          "all"
+#define POLICY_VOIP         "voip"
+#define POLICY_HIGH_LATENCY "high-latency"
+#define POLICY_HIGH_LATENCY_UHQA "high-latency-uhqa"
+#define POLICY_MIRRORING    "mirroring"
+#define POLICY_LOOPBACK    "loopback"
+
+/* API */
+#define BLUEZ_API           "bluez"
+#define ALSA_API            "alsa"
+#define HIGH_LATENCY_API    "high-latency"
+#define NULL_SOURCE         "source.null"
+#define ALSA_SAUDIOVOIP_CARD "saudiovoip"
+#define MONO_KEY                       VCONFKEY_SETAPPL_ACCESSIBILITY_MONO_AUDIO
+
+/* Sink Identify Macros */
+#define sink_is_hdmi(sink) !strncmp(sink->name, SINK_HDMI, strlen(SINK_HDMI))
+#define sink_is_highlatency(sink) !strncmp(sink->name, SINK_HIGH_LATENCY, strlen(SINK_HIGH_LATENCY))
+#define sink_is_alsa(sink) !strncmp(sink->name, SINK_ALSA, strlen(SINK_ALSA))
+#define sink_is_voip(sink) !strncmp(sink->name, SINK_VOIP, strlen(SINK_VOIP))
+
+/* Channels */
+#define CH_5_1 6
+#define CH_7_1 8
+#define CH_STEREO 2
+
+/* UHQA */
+/**
+  * UHQA sampling rate vary from 96 KHz to 192 KHz, currently the plan is to configure sink with highest sampling
+  * rate possible i.e. 192 KHz. So that < 192 KHz will be resampled and played. This will avoid creating multiple sinks
+  * for multiple rates
+  */
+#define UHQA_SAMPLING_RATE 192000
+#define UHQA_BASE_SAMPLING_RATE 96000
+
+/* PCM Dump */
+#define PA_DUMP_INI_DEFAULT_PATH                "/usr/etc/mmfw_audio_pcm_dump.ini"
+#define PA_DUMP_INI_TEMP_PATH                   "/opt/system/mmfw_audio_pcm_dump.ini"
+#define PA_DUMP_VCONF_KEY                       "memory/private/sound/pcm_dump"
+#define PA_DUMP_PLAYBACK_DECODER_OUT            0x00000001
+#define PA_DUMP_PLAYBACK_RESAMPLER_IN           0x00000008
+#define PA_DUMP_PLAYBACK_RESAMPLER_OUT          0x00000010
+#define PA_DUMP_CAPTURE_ENCODER_IN              0x80000000
+
+/* check if this sink is bluez */
+
+/* Vconf Keys */
+#define DEFAULT_BOOTING_SOUND_PATH "/usr/share/keysound/poweron.wav"
+#define VCONF_BOOTING "memory/private/sound/booting"
+#ifdef BURST_SHOT
+#define VCONF_SOUND_BURSTSHOT "memory/private/sound/burstshot"
+#endif
+
+/* boot sound */
+#define BOOTING_SOUND_SAMPLE "booting"
+
+
+typedef enum pa_hal_event_type {
+    PA_HAL_EVENT_LOAD_DEVICE,
+    PA_HAL_EVENT_OPEN_DEVICE,
+    PA_HAL_EVENT_CLOSE_ALL_DEVICES,
+    PA_HAL_EVENT_CLOSE_DEVICE,
+    PA_HAL_EVENT_UNLOAD_DEVICE,
+} pa_hal_event_type_t;
+
+struct pa_hal_device_event_data {
+    audio_device_info_t device_info;
+    audio_device_param_info_t params[AUDIO_DEVICE_PARAM_MAX];
+};
+
+struct pa_hal_event {
+    struct userdata *userdata;
+
+    pa_hal_event_type_t event_type;
+    void *event_data;
+
+    pa_cond *cond;
+    pa_mutex *mutex;
+
+    PA_LLIST_FIELDS(struct pa_hal_event);
+};
+
+#ifdef PRIMARY_VOLUME
+struct pa_primary_volume_type_info {
+    void* key;
+    int volumetype;
+    int priority;
+    PA_LLIST_FIELDS(struct pa_primary_volume_type_info);
+};
+#endif
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -43,43 +209,278 @@ struct userdata {
     pa_hook_slot *sink_input_new_hook_slot,*sink_put_hook_slot;
 
     pa_hook_slot *sink_input_unlink_slot,*sink_unlink_slot;
+    pa_hook_slot *sink_input_put_slot;
     pa_hook_slot *sink_input_unlink_post_slot, *sink_unlink_post_slot;
     pa_hook_slot *sink_input_move_start_slot,*sink_input_move_finish_slot;
+    pa_hook_slot *source_output_new_hook_slot, *source_output_unlink_post_slot;
+    pa_hook_slot *source_output_put_slot;
+    pa_hook_slot *sink_state_changed_slot;
+    pa_hook_slot *sink_input_state_changed_slot;
+
+    pthread_t tid;
+    pa_defer_event *defer_event;
+    PA_LLIST_HEAD(struct pa_hal_event, hal_event_queue);
+    struct pa_hal_event *hal_event_last;
+
     pa_subscription *subscription;
 
-    bool on_hotplug:1;
-    int        bt_off_idx;
+    pa_bool_t on_hotplug:1;
+    int bt_off_idx;
+
+    uint32_t session;
+    uint32_t subsession;
+    uint32_t subsession_opt;
+    uint32_t active_device_in;
+    uint32_t active_device_out;
+    uint32_t active_route_flag;
 
     int is_mono;
     float balance;
-    pa_module* module_mono_bt;
+    int muteall;
+    int call_muted;
+    pa_bool_t wideband;
+    int fragment_size;
+    int tsched_buffer_size;
+       pa_module* module_mono_bt;
     pa_module* module_combined;
     pa_module* module_mono_combined;
     pa_native_protocol *protocol;
-    pa_hook_slot *source_output_new_hook_slot;
+//    pa_hook_slot *source_output_new_hook_slot;
+#ifdef PRIMARY_VOLUME
+    PA_LLIST_HEAD(struct pa_primary_volume_type_info, primary_volume);
+#endif
+
+    struct {
+        void *dl_handle;
+        void *data;
+        audio_interface_t intf;
+    } audio_mgr;
+
+    struct  { // for burst-shot
+        pa_bool_t is_running;
+        pa_mutex* mutex;
+        int count; /* loop count */
+        pa_time_event *time_event;
+        pa_scache_entry *e;
+        pa_sink_input *i;
+        pa_memblockq *q;
+        pa_usec_t time_interval;
+        pa_usec_t factor; /* timer boosting */
+    } audio_sample_userdata;
+};
+
+enum {
+    CUSTOM_EXT_3D_LEVEL,
+    CUSTOM_EXT_BASS_LEVEL,
+    CUSTOM_EXT_CONCERT_HALL_VOLUME,
+    CUSTOM_EXT_CONCERT_HALL_LEVEL,
+    CUSTOM_EXT_CLARITY_LEVEL,
+    CUSTOM_EXT_PARAM_MAX
 };
 
 enum {
     SUBCOMMAND_TEST,
+    SUBCOMMAND_PLAY_SAMPLE,
+    SUBCOMMAND_PLAY_SAMPLE_CONTINUOUSLY,
     SUBCOMMAND_MONO,
     SUBCOMMAND_BALANCE,
+    SUBCOMMAND_MUTEALL,
+    SUBCOMMAND_SET_USE_CASE,
+    SUBCOMMAND_SET_SESSION,
+    SUBCOMMAND_SET_SUBSESSION,
+    SUBCOMMAND_SET_ACTIVE_DEVICE,
+    SUBCOMMAND_RESET,
+    SUBCOMMAND_GET_VOLUME_LEVEL_MAX,
+    SUBCOMMAND_GET_VOLUME_LEVEL,
+    SUBCOMMAND_SET_VOLUME_LEVEL,
+    SUBCOMMAND_UPDATE_VOLUME,
+    SUBCOMMAND_GET_MUTE,
+    SUBCOMMAND_SET_MUTE,
+    SUBCOMMAND_IS_AVAILABLE_HIGH_LATENCY,
+    SUBCOMMAND_UNLOAD_HDMI,
+
 };
+typedef enum
+{
+    DOCK_NONE      = 0,
+    DOCK_DESKDOCK  = 1,
+    DOCK_CARDOCK   = 2,
+    DOCK_AUDIODOCK = 7,
+    DOCK_SMARTDOCK = 8
+} DOCK_STATUS;
+
+static pa_sink *__get_real_master_sink(pa_sink_input *si);
+static pa_source *__get_real_master_source(pa_source_output *so);
+static inline int __compare_device_info(audio_device_info_t *device_info1, audio_device_info_t *device_info2);
+static audio_return_t __fill_audio_playback_stream_info(pa_proplist *sink_input_proplist, pa_sample_spec *sample_spec, audio_info_t *audio_info);
+static audio_return_t __fill_audio_playback_device_info(pa_proplist *sink_proplist, audio_info_t *audio_info);
+static audio_return_t __fill_audio_playback_info(pa_sink_input *si, audio_info_t *audio_info);
+static audio_return_t __fill_audio_capture_device_info(pa_proplist *source_proplist, audio_info_t *audio_info);
+static audio_return_t policy_play_sample(struct userdata *u, pa_native_connection *c, const char *name, uint32_t volume_type, uint32_t gain_type, uint32_t volume_level, uint32_t *stream_idx);
+static audio_return_t policy_reset(struct userdata *u);
+static audio_return_t policy_set_session(struct userdata *u, uint32_t session, uint32_t start);
+static audio_return_t policy_set_active_device(struct userdata *u, uint32_t device_in, uint32_t device_out, uint32_t* need_update);
+static audio_return_t policy_get_volume_level_max(struct userdata *u, uint32_t volume_type, uint32_t *volume_level);
+static audio_return_t __update_volume(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, uint32_t volume_level);
+#ifdef PRIMARY_VOLUME
+static int __set_primary_volume(struct userdata *u, void* key, int volumetype, int is_new);
+#endif
+static audio_return_t policy_get_volume_level(struct userdata *u, uint32_t stream_idx, uint32_t *volume_type, uint32_t *volume_level);
+static audio_return_t policy_set_volume_level(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, uint32_t volume_level);
+static audio_return_t policy_get_mute(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, uint32_t direction, uint32_t *mute);
+static audio_return_t policy_set_mute(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, uint32_t direction, uint32_t mute);
+static bool policy_is_filter (pa_sink_input* si);
+
+static const char *__get_session_str(uint32_t session)
+{
+    switch (session) {
+        case AUDIO_SESSION_MEDIA:                       return "media";
+        case AUDIO_SESSION_VOICECALL:                   return "voicecall";
+        case AUDIO_SESSION_VIDEOCALL:                   return "videocall";
+        case AUDIO_SESSION_VOIP:                        return "voip";
+        case AUDIO_SESSION_FMRADIO:                     return "fmradio";
+        case AUDIO_SESSION_CAMCORDER:                   return "camcorder";
+        case AUDIO_SESSION_NOTIFICATION:                return "notification";
+        case AUDIO_SESSION_ALARM:                       return "alarm";
+        case AUDIO_SESSION_EMERGENCY:                   return "emergency";
+        case AUDIO_SESSION_VOICE_RECOGNITION:           return "vr";
+        default:                                        return "invalid";
+    }
+}
+
+static const char *__get_subsession_str(uint32_t subsession)
+{
+    switch (subsession) {
+        case AUDIO_SUBSESSION_NONE:                     return "none";
+        case AUDIO_SUBSESSION_VOICE:                    return "voice";
+        case AUDIO_SUBSESSION_RINGTONE:                 return "ringtone";
+        case AUDIO_SUBSESSION_MEDIA:                    return "media";
+        case AUDIO_SUBSESSION_INIT:                     return "init";
+        case AUDIO_SUBSESSION_VR_NORMAL:                return "vr_normal";
+        case AUDIO_SUBSESSION_VR_DRIVE:                 return "vr_drive";
+        case AUDIO_SUBSESSION_STEREO_REC:               return "stereo_rec";
+        case AUDIO_SUBSESSION_MONO_REC:                 return "mono_rec";
+        default:                                        return "invalid";
+    }
+}
+
+static const char *__get_device_in_str(uint32_t device_in)
+{
+    switch (device_in) {
+        case AUDIO_DEVICE_IN_NONE:                      return "none";
+        case AUDIO_DEVICE_IN_MIC:                       return "mic";
+        case AUDIO_DEVICE_IN_WIRED_ACCESSORY:           return "wired";
+        case AUDIO_DEVICE_IN_BT_SCO:                    return "bt_sco";
+        default:                                        return "invalid";
+    }
+}
+
+static const char *__get_device_out_str(uint32_t device_out)
+{
+    switch (device_out) {
+        case AUDIO_DEVICE_OUT_NONE:                     return "none";
+        case AUDIO_DEVICE_OUT_SPEAKER:                  return "spk";
+        case AUDIO_DEVICE_OUT_RECEIVER:                 return "recv";
+        case AUDIO_DEVICE_OUT_WIRED_ACCESSORY:          return "wired";
+        case AUDIO_DEVICE_OUT_BT_SCO:                   return "bt_sco";
+        case AUDIO_DEVICE_OUT_BT_A2DP:                  return "bt_a2dp";
+        case AUDIO_DEVICE_OUT_DOCK:                     return "dock";
+        case AUDIO_DEVICE_OUT_HDMI:                     return "hdmi";
+        case AUDIO_DEVICE_OUT_MIRRORING:                return "mirror";
+        case AUDIO_DEVICE_OUT_USB_AUDIO:                return "usb";
+        case AUDIO_DEVICE_OUT_MULTIMEDIA_DOCK:          return "multi_dock";
+        default:                                        return "invalid";
+    }
+}
+#if 0
+static void __load_dump_config(struct userdata *u)
+{
+    dictionary * dict = NULL;
+    int vconf_dump = 0;
+
+    dict = iniparser_load(PA_DUMP_INI_DEFAULT_PATH);
+    if (!dict) {
+        pa_log_debug("%s load failed. Use temporary file", PA_DUMP_INI_DEFAULT_PATH);
+        dict = iniparser_load(PA_DUMP_INI_TEMP_PATH);
+        if (!dict) {
+            pa_log_warn("%s load failed", PA_DUMP_INI_TEMP_PATH);
+            return;
+        }
+    }
+
+    vconf_dump |= iniparser_getboolean(dict, "pcm_dump:decoder_out", 0) ? PA_DUMP_PLAYBACK_DECODER_OUT : 0;
+    vconf_dump |= iniparser_getboolean(dict, "pcm_dump:resampler_in", 0) ? PA_DUMP_PLAYBACK_RESAMPLER_IN : 0;
+    vconf_dump |= iniparser_getboolean(dict, "pcm_dump:resampler_out", 0) ? PA_DUMP_PLAYBACK_RESAMPLER_OUT : 0;
+    vconf_dump |= iniparser_getboolean(dict, "pcm_dump:encoder_in", 0) ? PA_DUMP_CAPTURE_ENCODER_IN : 0;
+    u->core->dump_sink = (pa_bool_t)iniparser_getboolean(dict, "pcm_dump:pa_sink", 0);
+    u->core->dump_sink_input = (pa_bool_t)iniparser_getboolean(dict, "pcm_dump:pa_sink_input", 0);
+    u->core->dump_source = (pa_bool_t)iniparser_getboolean(dict, "pcm_dump:pa_source", 0);
+    u->core->dump_source_output = (pa_bool_t)iniparser_getboolean(dict, "pcm_dump:pa_source_output", 0);
+
+    iniparser_freedict(dict);
+
+    if (vconf_set_int(PA_DUMP_VCONF_KEY, vconf_dump)) {
+        pa_log_warn("vconf_set_int %s=%x failed", PA_DUMP_VCONF_KEY, vconf_dump);
+    }
+}
+#endif
+static inline pa_bool_t __is_mute_policy(void)
+{
+    int sound_status = 1;
+
+    /* If sound is mute mode, force ringtone/notification path to headset */
+    if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sound_status)) {
+        pa_log_warn("vconf_get_bool for %s failed", VCONFKEY_SETAPPL_SOUND_STATUS_BOOL);
+    }
+
+    return (sound_status) ? false : true;
+}
+
+static inline pa_bool_t __is_recording(void)
+{
+    int capture_status = 0;
+
+    /* Check whether audio is recording */
+    if (vconf_get_int(VCONFKEY_SOUND_CAPTURE_STATUS, &capture_status)) {
+        pa_log_warn("vconf_get_bool for %s failed", VCONFKEY_SOUND_CAPTURE_STATUS);
+    }
+
+    return (capture_status) ? true : false;
+}
+
+static inline pa_bool_t __is_noise_reduction_on(void)
+{
+    int noise_reduction_on = 1;
+
+    if (vconf_get_bool(VCONFKEY_CALL_NOISE_REDUCTION_STATE_BOOL, &noise_reduction_on)) {
+        pa_log_warn("vconf_get_bool for %s failed", VCONFKEY_CALL_NOISE_REDUCTION_STATE_BOOL);
+    }
+
+    return (noise_reduction_on == 1) ? true : false;
+}
+
+static bool __is_extra_volume_on(void)
+{
+    int extra_volume_on = 1;
+
+    if (vconf_get_bool(VCONFKEY_CALL_EXTRA_VOLUME_STATE_BOOL, &extra_volume_on)) {
+        pa_log_warn("vconf_get_bool for %s failed", VCONFKEY_CALL_EXTRA_VOLUME_STATE_BOOL);
+    }
+
+    return (extra_volume_on == 1) ? true : false;
+}
+
+static bool __is_wideband(void)
+{
+    int wbamr = 1;
+
+    if (vconf_get_bool(VCONFKEY_CALL_WBAMR_STATE_BOOL, &wbamr)) {
+        pa_log_warn("vconf_get_bool for %s failed", VCONFKEY_CALL_WBAMR_STATE_BOOL);
+    }
+
+    return (wbamr == 1) ? true : false;
+}
 
-/* DEFINEs */
-#define AEC_SINK                       "alsa_output.0.analog-stereo.echo-cancel"
-#define AEC_SOURCE                     "alsa_input.0.analog-stereo.echo-cancel"
-#define        SINK_ALSA                       "alsa_output.0.analog-stereo"
-#define SINK_MONO_ALSA         "mono_alsa"
-#define SINK_MONO_BT           "mono_bt"
-#define SINK_COMBINED          "combined"
-#define SINK_MONO_COMBINED     "mono_combined"
-#define POLICY_AUTO                    "auto"
-#define POLICY_PHONE           "phone"
-#define POLICY_ALL                     "all"
-#define POLICY_VOIP                    "voip"
-#define BLUEZ_API                      "bluez"
-#define ALSA_API                       "alsa"
-#define MONO_KEY                       VCONFKEY_SETAPPL_ACCESSIBILITY_MONO_AUDIO
 
 /* check if this sink is bluez */
 static bool policy_is_bluez (pa_sink* sink)
@@ -188,14 +589,129 @@ static pa_sink* policy_get_bt_sink (pa_core *c)
        }
        return NULL;
 }
+/** This function chages the sink from normal sink to UHQA sink if UHQA sink is available*/
+static pa_sink* switch_to_uhqa_sink(pa_core *c, const char* policy)
+{
+    pa_sink_input *si = NULL;
+    uint32_t idx;
+    pa_sink* sink = NULL;
+    pa_sink* uhqa_sink = NULL;
+    pa_sink* def = pa_namereg_get_default_sink(c);
+    /** If default sink is HDMI sink*/
+    if (sink_is_hdmi(def)) {
+        uhqa_sink = policy_get_sink_by_name(c, SINK_HDMI_UHQA);
+        sink = policy_get_sink_by_name(c, SINK_HDMI);
+    /** If high latency UHQA policy means h:0,4 UHQA sink to be selected if h:0,4 UHQA sink already created*/
+    } else if (pa_streq(policy, POLICY_HIGH_LATENCY_UHQA)) {
+        uhqa_sink = policy_get_sink_by_name(c, SINK_HIGH_LATENCY_UHQA);
+        sink = policy_get_sink_by_name(c, SINK_HIGH_LATENCY);
+    } else if (pa_streq(policy, POLICY_AUTO_UHQA)) {   /** If UHQA policy choose UHQA sink*/
+        pa_log_info ("---------------------------------");
+
+        uhqa_sink = policy_get_sink_by_name(c, SINK_ALSA_UHQA);
+        sink = policy_get_sink_by_name(c, SINK_ALSA);
+    }
+    pa_log_info ("---------------------------------");
+    if (uhqa_sink != NULL) {
+        if (sink != NULL) {/** if the sink is null due to some reason ,it need to add protect code */
+
+            /** Check if normal sink is in not suspended state then suspend normal sik so that pcm handle is closed*/
+            if (PA_SINK_SUSPENDED != pa_sink_get_state(sink) ) {
+                pa_sink_suspend(sink, true, PA_SUSPEND_USER);
+            }
+            pa_log_info ("---------------------------------");
+
+            /** Check any sink input connected to normal sink then move them to UHQA sink*/
+            PA_IDXSET_FOREACH (si, sink->inputs, idx) {
+
+                /* Get role (if role is filter, skip it) */
+                if (policy_is_filter(si)) {
+                    continue;
+                }
+                pa_sink_input_move_to(si, uhqa_sink, false);
+            }
+        }
+        if (PA_SINK_SUSPENDED == pa_sink_get_state(uhqa_sink)) {
+            pa_sink_suspend(uhqa_sink, false, PA_SUSPEND_USER);
+        }
+        sink = uhqa_sink;
+    }
+
+    return sink;
+}
+/** This function choose normal sink if UHQA sink is in suspended state*/
+static pa_sink* switch_to_normal_sink(pa_core *c, const char* policy)
+{
+    pa_sink_input *si = NULL;
+    uint32_t idx;
+    pa_sink* sink = NULL;
+    pa_sink* uhqa_sink = NULL;
+    const char *sink_name  = SINK_ALSA;
+    pa_sink* def = NULL;
+
+    def = pa_namereg_get_default_sink(c);
+
+    if (pa_streq(policy, POLICY_PHONE) || pa_streq(policy, POLICY_ALL)) {
+      /** Get the UHQA sink */
+      uhqa_sink = policy_get_sink_by_name (c, SINK_ALSA_UHQA);
+    } else if (sink_is_hdmi(def)) {    /** If default sink is HDMI sink*/
+        /** Get the UHQA sink handle, if it exists then suspend it if not in use*/
+        uhqa_sink = policy_get_sink_by_name (c, SINK_HDMI_UHQA);
+        sink_name  = SINK_HDMI;
+    } else if(pa_streq(policy, POLICY_HIGH_LATENCY)) {      /** Choose the normal sink based on policy*/
+        /** Get the UHQA sink handle, if it exists then suspend it if not in use*/
+        uhqa_sink =  policy_get_sink_by_name(c, SINK_HIGH_LATENCY_UHQA);
+        sink_name  = SINK_HIGH_LATENCY;
+    } else {
+        /** Get the UHQA sink */
+        uhqa_sink = policy_get_sink_by_name(c, SINK_ALSA_UHQA);
+    }
+    sink = uhqa_sink;
+
+    /**
+      * If UHQA sink is in used or any UHQA sink is connected to UHQA sink then return UHQA sink else return normal sink
+      */
+    if ((sink != NULL) && pa_sink_used_by(sink)) {
+        sink = uhqa_sink;
+    } else {
+        sink = policy_get_sink_by_name(c, sink_name);
+        if (sink != NULL) {/**if the sink is null ,it need to add protect code*/
+            /** Move all sink inputs from UHQA sink to normal sink*/
+            if (uhqa_sink != NULL) {
+                if (PA_SINK_SUSPENDED != pa_sink_get_state(uhqa_sink)) {
+                    pa_sink_suspend(uhqa_sink, true, PA_SUSPEND_USER);
+                }
+                PA_IDXSET_FOREACH (si, uhqa_sink->inputs, idx) {
+                    /* Get role (if role is filter, skip it) */
+                    if (policy_is_filter(si)) {
+                       continue;
+                    }
+                   pa_sink_input_move_to(si, sink, false);
+               }
+            }
+            if (PA_SINK_SUSPENDED == pa_sink_get_state(policy_get_sink_by_name(c, sink_name)) ) {
+                /** unsuspend this sink */
+                pa_sink_suspend( policy_get_sink_by_name(c, sink_name), false, PA_SUSPEND_USER);
+            }
+        } else {/** if sink is null,it can not move to the normal sink ,still use uhqa sink */
+            pa_log_warn ("The %s sink is null", sink_name);
+            sink = uhqa_sink;
+        }
+    }
 
-/* Select sink for given condition */
-static pa_sink* policy_select_proper_sink (pa_core *c, const char* policy, int is_mono)
+    return sink;
+}
+/*Select sink for given condition */
+static pa_sink* policy_select_proper_sink (struct userdata *u, const char* policy, pa_sink_input *sink_input, int is_mono)
 {
+       pa_core *c = u->core;
        pa_sink* sink = NULL;
        pa_sink* bt_sink = NULL;
        pa_sink* def = NULL;
-
+       pa_sink* sink_null;
+       uint32_t idx;
+       const char *si_policy_str;
+       pa_sink_input *si = NULL;
        if (c == NULL || policy == NULL) {
                pa_log_warn ("input param is null");
                return NULL;
@@ -213,61 +729,2016 @@ static pa_sink* policy_select_proper_sink (pa_core *c, const char* policy, int i
        pa_log_debug ("[POLICY][%s] policy[%s], is_mono[%d], current default[%s], bt sink[%s]\n",
                        __func__, policy, is_mono, def->name, (bt_sink)? bt_sink->name:"null");
 
+    sink_null = (pa_sink *)pa_namereg_get(c, "null", PA_NAMEREG_SINK);
+    /* if default sink is set as null sink, we will use null sink */
+    if (def == sink_null)
+        return def;
+
        /* Select sink to */
        if (pa_streq(policy, POLICY_ALL)) {
                /* all */
                if (bt_sink) {
                        sink = policy_get_sink_by_name(c, (is_mono)? SINK_MONO_COMBINED : SINK_COMBINED);
                } else {
+#ifdef TIZEN_MICRO
                        sink = policy_get_sink_by_name (c, (is_mono)? SINK_MONO_ALSA : SINK_ALSA);
+#else
+            sink = switch_to_normal_sink(c, policy);
+#endif
                }
 
        } else if (pa_streq(policy, POLICY_PHONE)) {
                /* phone */
-               sink = policy_get_sink_by_name (c, (is_mono)? SINK_MONO_ALSA : SINK_ALSA);
+#ifdef TIZEN_MICRO
+        if (u->subsession == AUDIO_SUBSESSION_RINGTONE)
+            sink = policy_get_sink_by_name(c, AEC_SINK);
+        if (!sink)
+                       sink = policy_get_sink_by_name (c, (is_mono)? SINK_MONO_ALSA : SINK_ALSA);
+#else
+        sink = switch_to_normal_sink(c, policy);
+#endif
        } else if (pa_streq(policy, POLICY_VOIP)) {
                /* VOIP */
-               sink = policy_get_sink_by_name (c,AEC_SINK);
+               /* NOTE: Check voip sink first, if not available, use AEC sink */
+        sink = policy_get_sink_by_name (c,SINK_VOIP);
+        if (sink == NULL) {
+            pa_log_info ("VOIP sink is not available, try to use AEC sink");
+            sink = policy_get_sink_by_name (c, AEC_SINK);
+            if (sink == NULL) {
+                pa_log_info ("AEC sink is not available, set to default sink");
+                sink = def;
+            }
+        }
        } else {
                /* auto */
                if (policy_is_bluez(def)) {
                        sink = (is_mono)? policy_get_sink_by_name (c, SINK_MONO_BT) : def;
                } else if (policy_is_usb_alsa(def)) {
                        sink = def;
+               } else if (sink_is_hdmi(def)) {
+#ifdef TIZEN_MICRO
+            sink = def;
+#else
+            if (pa_streq(policy, POLICY_AUTO_UHQA) || (pa_streq(policy, POLICY_HIGH_LATENCY_UHQA))) {
+                sink = switch_to_uhqa_sink(c,policy);
+            }
+            else {
+                sink = switch_to_normal_sink(c, policy);
+            }
+#endif
                } else {
-                       sink = (is_mono)? policy_get_sink_by_name (c, SINK_MONO_ALSA) : def;
+            pa_bool_t highlatency_exist = 0;
+
+#ifdef TIZEN_MICRO
+            if(pa_streq(policy, POLICY_HIGH_LATENCY)) {
+#else
+            if ((pa_streq(policy, POLICY_HIGH_LATENCY)) || (pa_streq(policy, POLICY_HIGH_LATENCY_UHQA))) {
+#endif
+                PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
+                    if ((si_policy_str = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_POLICY))) {
+                        if (pa_streq(si_policy_str, POLICY_HIGH_LATENCY) && sink_is_highlatency(si->sink)
+                            && (sink_input == NULL || sink_input->index != si->index)) {
+                            highlatency_exist = 1;
+                            break;
+                        }
+                    }
+                }
+
+#ifdef TIZEN_MICRO
+                if (!highlatency_exist) {
+                    sink = policy_get_sink_by_name(c, SINK_HIGH_LATENCY);
+                }
+#else
+                /** If high latency UHQA policy means h:0,4 UHQA sink to be selected if h:0,4 UHQA sink already created*/
+                if (pa_streq(policy, POLICY_HIGH_LATENCY_UHQA)) {
+                    sink = switch_to_uhqa_sink(c,policy);
+                }
+
+                /**
+                  * If still sink is null means either policy is high-latency or UHQA sink does not exist
+                  * Normal sink need to be selected
+                  */
+                if (!highlatency_exist && (sink == NULL)) {
+                    sink = switch_to_normal_sink(c, policy);
+                }
+#endif
+            }
+#ifdef TIZEN_MICRO
+            if (!sink)
+                               sink = policy_get_sink_by_name (c, (is_mono)? SINK_MONO_ALSA : SINK_ALSA);
+
+#else
+            /** If sink is still null then it is required to choose hw:0,0 UHQA sink or normal sink  based on policy*/
+            if (!sink) {
+                /** If UHQA policy choose UHQA sink*/
+                if (pa_streq(policy, POLICY_AUTO_UHQA)) {
+                    sink = switch_to_uhqa_sink(c,policy);
+                }
+
+                /** If still no sink selected then select hw:0,0 normal sink this is the default case*/
+                if (!sink) {
+                    sink = switch_to_normal_sink(c,POLICY_AUTO);
+                }
+             }
+#endif
+        }
+       }
+
+       pa_log_debug ("[POLICY][%s] selected sink : [%s]\n", __func__, (sink)? sink->name : "null");
+       return sink;
+}
+static bool policy_is_filter (pa_sink_input* si)
+{
+       const char* role = NULL;
+
+       if (si == NULL) {
+               pa_log_warn ("input param sink-input is null");
+               return false;
+       }
+
+       if ((role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE))) {
+#ifdef DEBUG_DETAIL
+               pa_log_debug("[POLICY][%s] Role of sink input [%d] = %s", __func__, si->index, role);
+#endif
+               if (pa_streq(role, "filter")) {
+#ifdef DEBUG_DETAIL
+                       pa_log_debug("[POLICY] no need to change of sink for %s", role);
+#endif
+                       return true;
                }
        }
 
-       pa_log_debug ("[POLICY][%s] selected sink : [%s]\n", __func__, (sink)? sink->name : "null");
-       return sink;
-}
+       return false;
+}
+static pa_sink *__get_real_master_sink(pa_sink_input *si)
+{
+    const char *master_name;
+    pa_sink *s, *sink;
+
+    s = (si->origin_sink) ? si->origin_sink : si->sink;
+    master_name = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_MASTER_DEVICE);
+    if (master_name)
+        sink = pa_namereg_get(si->core, master_name, PA_NAMEREG_SINK);
+    else
+        sink = s;
+    return sink;
+}
+static pa_source *__get_real_master_source(pa_source_output *so)
+{
+    const char *master_name;
+    pa_source *s, *source;
+
+    s = (so->destination_source) ? so->destination_source : so->source;
+    master_name = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_MASTER_DEVICE);
+    if (master_name)
+        source = pa_namereg_get(so->core, master_name, PA_NAMEREG_SINK);
+    else
+        source = s;
+    return source;
+}
+
+static void __free_audio_stream_info (audio_info_t *audio_info)
+{
+    pa_xfree(audio_info->stream.name);
+}
+static void __free_audio_device_info (audio_info_t *audio_info)
+{
+    if (audio_info->device.api == AUDIO_DEVICE_API_ALSA) {
+        pa_xfree(audio_info->device.alsa.card_name);
+    } else if (audio_info->device.api == AUDIO_DEVICE_API_BLUEZ) {
+        pa_xfree(audio_info->device.bluez.protocol);
+    }
+    pa_xfree(audio_info->device.name);
+}
+static void __free_audio_info (audio_info_t *audio_info)
+{
+    __free_audio_stream_info(audio_info);
+    __free_audio_device_info(audio_info);
+}
+static audio_return_t __fill_audio_playback_stream_info(pa_proplist *sink_input_proplist, pa_sample_spec *sample_spec, audio_info_t *audio_info)
+{
+    const char *si_volume_type_str, *si_gain_type_str;
+
+    memset(&audio_info->stream, 0x00, sizeof(audio_stream_info_t));
+
+    if (!sink_input_proplist) {
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    audio_info->stream.name = strdup(pa_strnull(pa_proplist_gets(sink_input_proplist, PA_PROP_MEDIA_NAME)));
+    audio_info->stream.samplerate = sample_spec->rate;
+    audio_info->stream.channels = sample_spec->channels;
+    audio_info->stream.gain_type = AUDIO_GAIN_TYPE_DEFAULT;
+
+    /* Get volume type of sink input */
+    if ((si_volume_type_str = pa_proplist_gets(sink_input_proplist, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
+        pa_atou(si_volume_type_str, &audio_info->stream.volume_type);
+    } else {
+        pa_xfree(audio_info->stream.name);
+        return AUDIO_ERR_UNDEFINED;
+    }
+
+    /* Get gain type of sink input */
+    if ((si_gain_type_str = pa_proplist_gets(sink_input_proplist, PA_PROP_MEDIA_TIZEN_GAIN_TYPE))) {
+        pa_atou(si_gain_type_str, &audio_info->stream.gain_type);
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __fill_audio_playback_device_info(pa_proplist *sink_proplist, audio_info_t *audio_info)
+{
+    const char *s_device_api_str;
+
+    memset(&audio_info->device, 0x00, sizeof(audio_device_info_t));
+
+    if (!sink_proplist) {
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    /* Get device api */
+    if ((s_device_api_str = pa_proplist_gets(sink_proplist, PA_PROP_DEVICE_API))) {
+        audio_info->device.name = strdup(pa_strnull(pa_proplist_gets(sink_proplist, PA_PROP_DEVICE_STRING)));
+        if (pa_streq(s_device_api_str, "alsa")) {
+            const char *card_idx_str, *device_idx_str;
+
+            audio_info->device.api = AUDIO_DEVICE_API_ALSA;
+            audio_info->device.direction = AUDIO_DIRECTION_OUT;
+            audio_info->device.alsa.card_name = strdup(pa_strnull(pa_proplist_gets(sink_proplist, "alsa.card_name")));
+            audio_info->device.alsa.card_idx = 0;
+            audio_info->device.alsa.device_idx = 0;
+            if ((card_idx_str = pa_proplist_gets(sink_proplist, "alsa.card")))
+                pa_atou(card_idx_str, &audio_info->device.alsa.card_idx);
+            if ((device_idx_str = pa_proplist_gets(sink_proplist, "alsa.device")))
+                pa_atou(device_idx_str, &audio_info->device.alsa.device_idx);
+        }
+        else if (pa_streq(s_device_api_str, "bluez")) {
+            const char *nrec_str;
+
+            audio_info->device.api = AUDIO_DEVICE_API_BLUEZ;
+            audio_info->device.bluez.nrec = 0;
+            audio_info->device.bluez.protocol = strdup(pa_strnull(pa_proplist_gets(sink_proplist, "bluetooth.protocol")));
+            if ((nrec_str = pa_proplist_gets(sink_proplist, "bluetooth.nrec")))
+                pa_atou(nrec_str, &audio_info->device.bluez.nrec);
+        }
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __fill_audio_playback_info(pa_sink_input *si, audio_info_t *audio_info)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    pa_sink *sink;
+
+    sink = __get_real_master_sink(si);
+    if (AUDIO_IS_ERROR((audio_ret = __fill_audio_playback_stream_info(si->proplist, &si->sample_spec, audio_info)))) {
+        return audio_ret;
+    }
+    if (AUDIO_IS_ERROR((audio_ret = __fill_audio_playback_device_info(sink->proplist, audio_info)))) {
+        __free_audio_stream_info(audio_info);
+        return audio_ret;
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __fill_audio_capture_device_info(pa_proplist *source_proplist, audio_info_t *audio_info)
+{
+    const char *s_device_api_str;
+
+    if (!source_proplist) {
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    memset(&audio_info->device, 0x00, sizeof(audio_device_info_t));
+
+    /* Get device api */
+    if ((s_device_api_str = pa_proplist_gets(source_proplist, PA_PROP_DEVICE_API))) {
+        audio_info->device.name = strdup(pa_strnull(pa_proplist_gets(source_proplist, PA_PROP_DEVICE_STRING)));
+        if (pa_streq(s_device_api_str, "alsa")) {
+            const char *card_idx_str, *device_idx_str;
+
+            audio_info->device.api = AUDIO_DEVICE_API_ALSA;
+            audio_info->device.direction = AUDIO_DIRECTION_IN;
+            audio_info->device.alsa.card_name = strdup(pa_strnull(pa_proplist_gets(source_proplist, "alsa.card_name")));
+            audio_info->device.alsa.card_idx = 0;
+            audio_info->device.alsa.device_idx = 0;
+            if ((card_idx_str = pa_proplist_gets(source_proplist, "alsa.card")))
+                pa_atou(card_idx_str, &audio_info->device.alsa.card_idx);
+            if ((device_idx_str = pa_proplist_gets(source_proplist, "alsa.device")))
+                pa_atou(device_idx_str, &audio_info->device.alsa.device_idx);
+        }
+        else if (pa_streq(s_device_api_str, "bluez")) {
+            const char *nrec_str;
+
+            audio_info->device.api = AUDIO_DEVICE_API_BLUEZ;
+            audio_info->device.bluez.nrec = 0;
+            audio_info->device.bluez.protocol = strdup(pa_strnull(pa_proplist_gets(source_proplist, "bluetooth.protocol")));
+            if ((nrec_str = pa_proplist_gets(source_proplist, "bluetooth.nrec")))
+                pa_atou(nrec_str, &audio_info->device.bluez.nrec);
+        }
+    }
+
+    return AUDIO_RET_OK;
+}
+
+#define PROP_POLICY_CORK "policy_cork_by_device_switch"
+
+static inline int __compare_device_info (audio_device_info_t *device_info1, audio_device_info_t *device_info2)
+{
+    if (device_info1->direction != device_info2->direction)
+        return false;
+
+    if (device_info1->api == AUDIO_DEVICE_API_ALSA) {
+        if ((!strcmp(device_info1->alsa.card_name, device_info2->alsa.card_name) || (device_info1->alsa.card_idx == device_info2->alsa.card_idx))
+            && (device_info1->alsa.device_idx == device_info2->alsa.device_idx)) {
+            return true;
+        }
+    }
+    if (device_info1->api == AUDIO_DEVICE_API_BLUEZ) {
+        if (!strcmp(device_info1->bluez.protocol, device_info2->bluez.protocol) && (device_info1->bluez.nrec == device_info2->bluez.nrec)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static void __free_event (struct pa_hal_event *hal_event) {
+    pa_assert(hal_event);
+    pa_assert(hal_event->userdata);
+
+    pa_xfree(hal_event->event_data);
+    pa_mutex_free(hal_event->mutex);
+    pa_cond_free(hal_event->cond);
+    pa_xfree(hal_event);
+}
+
+static inline const char *__get_event_type_string (pa_hal_event_type_t hal_event_type)
+{
+    switch (hal_event_type) {
+        case PA_HAL_EVENT_LOAD_DEVICE:          return "load device";
+        case PA_HAL_EVENT_OPEN_DEVICE:          return "open device";
+        case PA_HAL_EVENT_CLOSE_ALL_DEVICES:    return "close all devices";
+        case PA_HAL_EVENT_CLOSE_DEVICE:         return "close device";
+        case PA_HAL_EVENT_UNLOAD_DEVICE:        return "unload device";
+        default:                                return "undefined";
+    }
+}
+static audio_return_t __load_n_open_device (struct userdata *u, audio_device_info_t *device_info, audio_device_param_info_t *params, pa_hal_event_type_t hal_event_type)
+{
+    audio_info_t audio_info;
+    bool is_module_loaded = false;
+    pa_strbuf *name_buf, *args_buf, *prop_buf;
+    char *name = NULL, *args = NULL, *prop = NULL;
+    pa_source *source;
+    pa_sink *sink;
+    const char *device_object_str = NULL, *dirction_str = NULL;
+    const char *is_manual_corked_str = NULL;
+    uint32_t is_manual_corked = 0;
+    int i;
+    bool is_param_set[AUDIO_DEVICE_PARAM_MAX] = {false, };
+    uint32_t idx;
+
+    pa_assert(u);
+    pa_assert(device_info);
+    pa_assert(device_info->direction == AUDIO_DIRECTION_IN || device_info->direction == AUDIO_DIRECTION_OUT);
+
+     if (device_info->direction == AUDIO_DIRECTION_IN) {
+        PA_IDXSET_FOREACH(source, u->core->sources, idx) {
+            if (!AUDIO_IS_ERROR(__fill_audio_capture_device_info(source->proplist, &audio_info))) {
+                if (__compare_device_info(&audio_info.device, device_info)) {
+                    is_module_loaded = true;
+                    __free_audio_device_info(&audio_info);
+                    break;
+                }
+                __free_audio_device_info(&audio_info);
+            }
+        }
+        device_object_str = "source";
+        dirction_str = "input";
+    } else {
+        PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
+            if (!AUDIO_IS_ERROR(__fill_audio_playback_device_info(sink->proplist, &audio_info))) {
+                if (__compare_device_info(&audio_info.device, device_info)) {
+                    is_module_loaded = true;
+                    __free_audio_device_info(&audio_info);
+                    break;
+                }
+                __free_audio_device_info(&audio_info);
+            }
+        }
+        device_object_str = "sink";
+        dirction_str = "output";
+    }
+
+    name_buf = pa_strbuf_new();
+    if (device_info->api == AUDIO_DEVICE_API_ALSA) {
+        if (device_info->alsa.card_name && !strncmp(device_info->alsa.card_name, ALSA_VIRTUAL_CARD, strlen(ALSA_VIRTUAL_CARD))) {
+            pa_strbuf_printf(name_buf, "%s", (device_info->direction == AUDIO_DIRECTION_OUT) ? SINK_VIRTUAL : SOURCE_VIRTUAL);
+        } else if (device_info->alsa.card_name && !strncmp(device_info->alsa.card_name, ALSA_SAUDIOVOIP_CARD, strlen(ALSA_SAUDIOVOIP_CARD))) {
+            pa_strbuf_printf(name_buf, "%s", (device_info->direction == AUDIO_DIRECTION_OUT) ? SINK_VOIP : SOURCE_VOIP);
+        } else {
+            pa_strbuf_printf(name_buf, "alsa_%s.%d.analog-stereo", dirction_str, device_info->alsa.device_idx);
+        }
+    } else if (device_info->api == AUDIO_DEVICE_API_BLUEZ) {
+        /* HAL_TODO : do we need to consider BLUEZ here? */
+        pa_strbuf_printf(name_buf, "bluez_%s.%s", device_object_str, device_info->bluez.protocol);
+    } else {
+        pa_strbuf_printf(name_buf, "unknown_%s", device_object_str);
+    }
+    name = pa_strbuf_tostring_free(name_buf);
+    if (!name) {
+        pa_log_error("invalid module name");
+        return AUDIO_ERR_PARAMETER;
+    }
+
+    /* load module if is not loaded */
+    if (is_module_loaded == false) {
+        args_buf = pa_strbuf_new();
+        prop_buf = pa_strbuf_new();
+
+        pa_strbuf_printf(args_buf, "%s_name=\"%s\" ", device_object_str, name);
+        if (device_info->name) {
+            pa_strbuf_printf(args_buf, "device=\"%s\" ", device_info->name);
+        }
+
+        for (i = 0; i < AUDIO_DEVICE_PARAM_MAX; i++) {
+            if (params[i].param == AUDIO_DEVICE_PARAM_NONE)
+                break;
+            is_param_set[params[i].param] = true;
+            if (params[i].param == AUDIO_DEVICE_PARAM_CHANNELS) {
+                pa_strbuf_printf(args_buf, "channels=\"%d\" ", params[i].u32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_SAMPLERATE) {
+                pa_strbuf_printf(args_buf, "rate=\"%d\" ", params[i].u32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_FRAGMENT_SIZE) {
+                pa_strbuf_printf(args_buf, "fragment_size=\"%d\" ", params[i].u32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_FRAGMENT_NB) {
+                pa_strbuf_printf(args_buf, "fragments=\"%d\" ", params[i].u32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_START_THRESHOLD) {
+                pa_strbuf_printf(args_buf, "start_threshold=\"%d\" ", params[i].s32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_USE_MMAP) {
+                pa_strbuf_printf(args_buf, "mmap=\"%d\" ", params[i].u32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_USE_TSCHED) {
+                pa_strbuf_printf(args_buf, "tsched=\"%d\" ", params[i].u32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_TSCHED_BUF_SIZE) {
+                pa_strbuf_printf(args_buf, "tsched_buffer_size=\"%d\" ", params[i].u32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_SUSPEND_TIMEOUT) {
+                pa_strbuf_printf(prop_buf, "module-suspend-on-idle.timeout=%d ", params[i].u32_v);
+            } else if (params[i].param == AUDIO_DEVICE_PARAM_ALTERNATE_RATE) {
+                pa_strbuf_printf(args_buf, "alternate_rate=\"%d\" ", params[i].u32_v);
+            }
+        }
+
+        if (device_info->direction == AUDIO_DIRECTION_IN) {
+            pa_module *module_source = NULL;
+
+            if (!is_param_set[AUDIO_DEVICE_PARAM_FRAGMENT_SIZE]) {
+                pa_strbuf_printf(args_buf, "fragment_size=\"%d\" ", (u->fragment_size) ? u->fragment_size : DEFAULT_FRAGMENT_SIZE);
+            }
+            if ((prop = pa_strbuf_tostring_free(prop_buf))) {
+                pa_strbuf_printf(args_buf, "source_properties=\"%s\" ", prop);
+            }
+
+            args = pa_strbuf_tostring_free(args_buf);
+
+            if (device_info->api == AUDIO_DEVICE_API_ALSA) {
+                module_source = pa_module_load(u->core, "module-alsa-source", args);
+            } else if (device_info->api == AUDIO_DEVICE_API_BLUEZ) {
+                module_source = pa_module_load(u->core, "module-bluez-source", args);
+            }
+
+            if (!module_source) {
+                pa_log_error("load source module failed. api:%d args:%s", device_info->api, args);
+            }
+        } else {
+            pa_module *module_sink = NULL;
+
+            if (!is_param_set[AUDIO_DEVICE_PARAM_TSCHED_BUF_SIZE]) {
+                pa_strbuf_printf(args_buf, "tsched_buffer_size=\"%d\" ", (u->tsched_buffer_size) ? u->tsched_buffer_size : DEFAULT_TSCHED_BUFFER_SIZE);
+            }
+            if ((prop = pa_strbuf_tostring_free(prop_buf))) {
+                pa_strbuf_printf(args_buf, "sink_properties=\"%s\" ", prop);
+            }
+
+            args = pa_strbuf_tostring_free(args_buf);
+
+            if (device_info->api == AUDIO_DEVICE_API_ALSA) {
+                module_sink = pa_module_load(u->core, "module-alsa-sink", args);
+            } else if (device_info->api == AUDIO_DEVICE_API_BLUEZ) {
+                module_sink = pa_module_load(u->core, "module-bluez-sink", args);
+            }
+
+            if (!module_sink) {
+                pa_log_error("load sink module failed. api:%d args:%s", device_info->api, args);
+            }
+        }
+    }
+
+    if (hal_event_type == PA_HAL_EVENT_LOAD_DEVICE) {
+        goto exit;
+    }
+
+    if (device_info->direction == AUDIO_DIRECTION_IN) {
+        /* set default source */
+        pa_source *source_default = pa_namereg_get_default_source(u->core);
+        pa_source *source_null = (pa_source *)pa_namereg_get(u->core, "null", PA_NAMEREG_SOURCE);
+
+        if (source_default == source_null || device_info->is_default_device) {
+            if ((source = pa_namereg_get(u->core, name, PA_NAMEREG_SOURCE))) {
+                pa_source_output *so;
+
+                if (source != source_default) {
+                    pa_namereg_set_default_source(u->core, source);
+                    pa_log_info("set %s as default source", name);
+                }
+
+                PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
+                    if (!so->source)
+                        continue;
+                    /* Get role (if role is filter, skip it) */
+                    if (policy_is_filter(so->proplist))
+                        continue;
+
+                    pa_source_output_move_to(so, source, false);
+
+                    /* UnCork if corked by manually */
+                    if ((is_manual_corked_str = pa_proplist_gets(so->proplist, PROP_POLICY_CORK))) {
+                        pa_atou(is_manual_corked_str, &is_manual_corked);
+                        if (is_manual_corked) {
+                            pa_proplist_sets(so->proplist, PROP_POLICY_CORK, "0");
+                            pa_source_output_cork(so, false);
+                            pa_log_info("<UnCork> for source-input[%d]:source[%s]", so->index, so->source->name);
+                        }
+                    }
+                }
+            }
+        }
+    } else {
+        /* set default sink */
+        pa_sink *sink_default = pa_namereg_get_default_sink(u->core);
+        pa_sink *sink_null = (pa_sink *)pa_namereg_get(u->core, "null", PA_NAMEREG_SINK);
+
+        if ((sink_default == sink_null || device_info->is_default_device)
+            && !(device_info->api == AUDIO_DEVICE_API_ALSA && u->active_device_out == AUDIO_DEVICE_OUT_BT_A2DP)) {
+            if ((sink = pa_namereg_get(u->core, name, PA_NAMEREG_SINK))) {
+                pa_sink_input *si;
+
+                if (sink != sink_default) {
+                    pa_namereg_set_default_sink(u->core, sink);
+                    pa_log_info("set %s as default sink", name);
+                }
+
+                PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+                    if (!si->sink)
+                        continue;
+
+                    /* Get role (if role is filter, skip it) */
+                    if (policy_is_filter(si->proplist))
+                        continue;
+
+                    pa_sink_input_move_to(si, sink, false);
+
+                    /* UnCork if corked by manually */
+                    if ((is_manual_corked_str = pa_proplist_gets(si->proplist, PROP_POLICY_CORK))) {
+                        pa_atou(is_manual_corked_str, &is_manual_corked);
+                        if (is_manual_corked) {
+                            pa_proplist_sets(si->proplist, PROP_POLICY_CORK, "0");
+                            pa_sink_input_cork(si, false);
+                            pa_log_info("<UnCork> for sink-input[%d]:sink[%s]", si->index, si->sink->name);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+exit:
+    pa_xfree(name);
+    pa_xfree(args);
+    pa_xfree(prop);
+
+    return AUDIO_RET_OK;
+}
+static audio_return_t __load_n_open_device_callback (void *platform_data, audio_device_info_t *device_info, audio_device_param_info_t *params, pa_hal_event_type_t hal_event_type)
+{
+    struct userdata *u = (struct userdata *)platform_data;
+    struct pa_hal_event *hal_event;
+    struct pa_hal_device_event_data *event_data;
+
+    pa_assert(u);
+    pa_assert(device_info);
+    pa_assert(device_info->direction == AUDIO_DIRECTION_IN || device_info->direction == AUDIO_DIRECTION_OUT);
+    pa_assert(hal_event_type == PA_HAL_EVENT_LOAD_DEVICE || hal_event_type == PA_HAL_EVENT_OPEN_DEVICE);
+
+    if (u->tid != pthread_self()) {
+        /* called from thread */
+        pa_log_debug("%s is called within thread", __get_event_type_string(hal_event_type));
+
+        hal_event = pa_xmalloc(sizeof(struct pa_hal_event));
+        hal_event->userdata = u;
+        hal_event->event_type = hal_event_type;
+        event_data = pa_xmalloc(sizeof(struct pa_hal_device_event_data));
+        memcpy(&event_data->device_info, device_info, sizeof(audio_device_info_t));
+        memcpy(&event_data->params[0], params, sizeof(audio_device_param_info_t) * AUDIO_DEVICE_PARAM_MAX);
+        hal_event->event_data = (void *)event_data;
+
+        hal_event->mutex = pa_mutex_new(true, true);
+        hal_event->cond = pa_cond_new();
+
+        pa_mutex_lock(hal_event->mutex);
+
+        PA_LLIST_INSERT_AFTER(struct pa_hal_event, u->hal_event_queue, u->hal_event_last, hal_event);
+        u->hal_event_last = hal_event;
+
+        u->core->mainloop->defer_enable(u->defer_event, 1);
+
+        pa_cond_wait(hal_event->cond, hal_event->mutex);
+        pa_mutex_unlock(hal_event->mutex);
+
+        pa_log_info("%s is finished within thread", __get_event_type_string(hal_event_type));
+
+        __free_event(hal_event);
+    } else {
+        /* called from mainloop */
+        pa_log_debug("%s is called within mainloop", __get_event_type_string(hal_event_type));
+        __load_n_open_device(u, device_info, params, hal_event_type);
+        pa_log_info("%s is finished within mainloop", __get_event_type_string(hal_event_type));
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __load_device_callback (void *platform_data, audio_device_info_t *device_info, audio_device_param_info_t *params)
+{
+    return __load_n_open_device_callback(platform_data, device_info, params, PA_HAL_EVENT_LOAD_DEVICE);
+}
+
+static audio_return_t __open_device_callback (void *platform_data, audio_device_info_t *device_info, audio_device_param_info_t *params)
+{
+    return __load_n_open_device_callback(platform_data, device_info, params, PA_HAL_EVENT_OPEN_DEVICE);
+}
+
+
+static audio_return_t __close_all_devices (struct userdata *u)
+{
+    pa_source *source_null, *source;
+    pa_source_output *so;
+    pa_sink *sink_null, *sink;
+    pa_sink_input *si;
+    uint32_t idx;
+
+    pa_assert(u);
+
+    /* set default sink/src as null */
+    source_null = (pa_source *)pa_namereg_get(u->core, "null", PA_NAMEREG_SOURCE);
+    pa_namereg_set_default_source(u->core, source_null);
+    sink_null = (pa_sink *)pa_namereg_get(u->core, "null", PA_NAMEREG_SINK);
+    pa_namereg_set_default_sink(u->core, sink_null);
+
+    /* close input devices */
+    PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
+        if (!so->source)
+            continue;
+#if 0
+        /* Get role (if role is filter, skip it) */
+        if (policy_is_filter(so->proplist))
+            continue;
+#endif
+        /* Cork only if source-output was Running */
+        if (pa_source_output_get_state(so) == PA_SOURCE_OUTPUT_RUNNING) {
+            pa_proplist_sets(so->proplist, PROP_POLICY_CORK, "1");
+            pa_source_output_cork(so, true);
+            pa_log_info("<Cork> for source-output[%d]:source[%s]", so->index, so->source->name);
+        }
+        if (source_null)
+            pa_source_output_move_to(so, source_null, false);
+    }
+    PA_IDXSET_FOREACH(source, u->core->sources, idx) {
+        pa_source_suspend(source, true, PA_SUSPEND_INTERNAL);
+    }
+
+    /* close output devices */
+    PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+        if (!si->sink)
+            continue;
+        /* Get role (if role is filter, skip it) */
+        if (policy_is_filter(si))
+            continue;
+        /* Cork only if sink-input was Running */
+        if (pa_sink_input_get_state(si) == PA_SINK_INPUT_RUNNING) {
+            pa_proplist_sets(si->proplist, PROP_POLICY_CORK, "1");
+            pa_sink_input_cork(si, true);
+            pa_log_info("<Cork> for sink-input[%d]:sink[%s]", si->index, si->sink->name);
+        }
+        if (sink_null)
+            pa_sink_input_move_to(si, sink_null, false);
+    }
+    PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
+        pa_sink_suspend(sink, true, PA_SUSPEND_INTERNAL);
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __close_all_devices_callback (void *platform_data)
+{
+    struct userdata *u = (struct userdata *)platform_data;
+    struct pa_hal_event *hal_event;
+
+    pa_assert(u);
+
+    if (u->tid != pthread_self()) {
+        /* called from thread */
+        pa_log_debug("%s is called within thread", __get_event_type_string(PA_HAL_EVENT_CLOSE_ALL_DEVICES));
+
+        hal_event = pa_xmalloc(sizeof(struct pa_hal_event));
+        hal_event->userdata = u;
+        hal_event->event_type = PA_HAL_EVENT_CLOSE_ALL_DEVICES;
+        hal_event->event_data = NULL;
+
+        hal_event->mutex = pa_mutex_new(true, true);
+        hal_event->cond = pa_cond_new();
+
+        pa_mutex_lock(hal_event->mutex);
+
+        PA_LLIST_INSERT_AFTER(struct pa_hal_event, u->hal_event_queue, u->hal_event_last, hal_event);
+        u->hal_event_last = hal_event;
+
+        u->core->mainloop->defer_enable(u->defer_event, 1);
+
+        pa_cond_wait(hal_event->cond, hal_event->mutex);
+        pa_mutex_unlock(hal_event->mutex);
+
+        pa_log_info("%s is finished within thread", __get_event_type_string(PA_HAL_EVENT_CLOSE_ALL_DEVICES));
+
+        __free_event(hal_event);
+    } else {
+        /* called from mainloop */
+        pa_log_debug("%s is called within mainloop", __get_event_type_string(PA_HAL_EVENT_CLOSE_ALL_DEVICES));
+        __close_all_devices(u);
+        pa_log_info("%s is finished within mainloop", __get_event_type_string(PA_HAL_EVENT_CLOSE_ALL_DEVICES));
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __close_n_unload_device (struct userdata *u, audio_device_info_t *device_info, pa_hal_event_type_t hal_event_type)
+{
+    audio_info_t audio_info;
+    bool is_module_loaded = false;
+    pa_source *source_null, *source;
+    pa_source_output *so;
+    pa_sink *sink_null, *sink;
+    pa_sink_input *si;
+    uint32_t idx;
+
+    pa_assert(u);
+    pa_assert(device_info);
+    pa_assert(device_info->direction == AUDIO_DIRECTION_IN || device_info->direction == AUDIO_DIRECTION_OUT);
+
+     if (device_info->direction == AUDIO_DIRECTION_IN) {
+        PA_IDXSET_FOREACH(source, u->core->sources, idx) {
+            if (!AUDIO_IS_ERROR(__fill_audio_capture_device_info(source->proplist, &audio_info))) {
+                if (__compare_device_info(&audio_info.device, device_info)) {
+                    is_module_loaded = true;
+                    __free_audio_device_info(&audio_info);
+                    break;
+                }
+            }
+            __free_audio_device_info(&audio_info);
+        }
+
+        if (is_module_loaded) {
+            source_null = (pa_source *)pa_namereg_get(u->core, "null", PA_NAMEREG_SOURCE);
+            if (pa_namereg_get_default_source(u->core) == source) {
+                pa_namereg_set_default_source(u->core, source_null);
+            }
+
+            PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
+                if (__get_real_master_source(so) != source)
+                    continue;
+                /* Get role (if role is filter, skip it) */
+#if 0
+                if (policy_is_filter(so->proplist))
+                    continue;
+#endif
+                /* Cork only if source-output was Running */
+                if (pa_source_output_get_state(so) == PA_SOURCE_OUTPUT_RUNNING) {
+                    pa_proplist_sets(so->proplist, PROP_POLICY_CORK, "1");
+                    pa_source_output_cork(so, true);
+                    pa_log_info("<Cork> for source-output[%d]:source[%s]", so->index, so->source->name);
+                }
+                if (source_null)
+                    pa_source_output_move_to(so, source_null, false);
+            }
+            pa_source_suspend(source, true, PA_SUSPEND_INTERNAL);
+
+            if (hal_event_type == PA_HAL_EVENT_UNLOAD_DEVICE) {
+                pa_module_unload(u->core, source->module, true);
+            }
+        }
+    } else {
+        PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
+            if (!AUDIO_IS_ERROR(__fill_audio_playback_device_info(sink->proplist, &audio_info))) {
+                if (__compare_device_info(&audio_info.device, device_info)) {
+                    is_module_loaded = true;
+                    __free_audio_device_info(&audio_info);
+                    break;
+                }
+            }
+            __free_audio_device_info(&audio_info);
+        }
+
+        if (is_module_loaded) {
+            sink_null = (pa_sink *)pa_namereg_get(u->core, "null", PA_NAMEREG_SINK);
+            if (pa_namereg_get_default_sink(u->core) == sink) {
+                pa_namereg_set_default_sink(u->core, sink_null);
+            }
+
+            PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+                if (__get_real_master_sink(si) != sink)
+                    continue;
+                /* Get role (if role is filter, skip it) */
+                if (policy_is_filter(si))
+                    continue;
+                /* Cork only if sink-input was Running */
+                if (pa_sink_input_get_state(si) == PA_SINK_INPUT_RUNNING) {
+                    pa_proplist_sets(si->proplist, PROP_POLICY_CORK, "1");
+                    pa_sink_input_cork(si, true);
+                    pa_log_info("<Cork> for sink-input[%d]:sink[%s]", si->index, si->sink->name);
+                }
+                if (sink_null)
+                    pa_sink_input_move_to(si, sink_null, false);
+            }
+            pa_sink_suspend(sink, true, PA_SUSPEND_INTERNAL);
+
+            if (hal_event_type == PA_HAL_EVENT_UNLOAD_DEVICE) {
+                pa_module_unload(u->core, sink->module, true);
+            }
+        }
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __close_n_unload_device_callback (void *platform_data, audio_device_info_t *device_info, pa_hal_event_type_t hal_event_type)
+{
+    struct userdata *u = (struct userdata *)platform_data;
+    struct pa_hal_event *hal_event;
+    struct pa_hal_device_event_data *event_data;
+
+    pa_assert(u);
+    pa_assert(device_info);
+    pa_assert(device_info->direction == AUDIO_DIRECTION_IN || device_info->direction == AUDIO_DIRECTION_OUT);
+    pa_assert(hal_event_type == PA_HAL_EVENT_CLOSE_DEVICE || hal_event_type == PA_HAL_EVENT_UNLOAD_DEVICE);
+
+    if (u->tid != pthread_self()) {
+        /* called from thread */
+        pa_log_debug("%s is called within thread", __get_event_type_string(hal_event_type));
+
+        hal_event = pa_xmalloc(sizeof(struct pa_hal_event));
+        hal_event->userdata = u;
+        hal_event->event_type = hal_event_type;
+        event_data = pa_xmalloc(sizeof(struct pa_hal_device_event_data));
+        memcpy(&event_data->device_info, device_info, sizeof(audio_device_info_t));
+        hal_event->event_data = (void *)event_data;
+
+        hal_event->mutex = pa_mutex_new(true, true);
+        hal_event->cond = pa_cond_new();
+
+        pa_mutex_lock(hal_event->mutex);
+
+        PA_LLIST_INSERT_AFTER(struct pa_hal_event, u->hal_event_queue, u->hal_event_last, hal_event);
+        u->hal_event_last = hal_event;
+
+        u->core->mainloop->defer_enable(u->defer_event, 1);
+
+        pa_cond_wait(hal_event->cond, hal_event->mutex);
+        pa_mutex_unlock(hal_event->mutex);
+
+        pa_log_info("%s is finished within thread", __get_event_type_string(hal_event_type));
+
+        __free_event(hal_event);
+    } else {
+        /* called from mainloop */
+        pa_log_debug("%s is called within mainloop", __get_event_type_string(hal_event_type));
+        __close_n_unload_device(u, device_info, hal_event_type);
+        pa_log_info("%s is finished within mainloop", __get_event_type_string(hal_event_type));
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __close_device_callback (void *platform_data, audio_device_info_t *device_info)
+{
+    return __close_n_unload_device_callback(platform_data, device_info, PA_HAL_EVENT_CLOSE_DEVICE);
+}
+
+static audio_return_t __unload_device_callback (void *platform_data, audio_device_info_t *device_info)
+{
+    return __close_n_unload_device_callback(platform_data, device_info, PA_HAL_EVENT_UNLOAD_DEVICE);
+}
+
+static uint32_t __get_route_flag(struct userdata *u) {
+    uint32_t route_flag = 0;
+
+    if (u->session == AUDIO_SESSION_VOICECALL || u->session == AUDIO_SESSION_VIDEOCALL) {
+        if (u->subsession == AUDIO_SUBSESSION_RINGTONE) {
+            if (__is_mute_policy()) {
+                route_flag |= AUDIO_ROUTE_FLAG_MUTE_POLICY;
+            }
+            else if (!__is_recording()) {
+               route_flag |= AUDIO_ROUTE_FLAG_DUAL_OUT;
+            }
+        } else {
+            if (__is_noise_reduction_on())
+                route_flag |= AUDIO_ROUTE_FLAG_NOISE_REDUCTION;
+            if (__is_extra_volume_on())
+                route_flag |= AUDIO_ROUTE_FLAG_EXTRA_VOL;
+            if (__is_wideband())
+                route_flag |= AUDIO_ROUTE_FLAG_NETWORK_WB;
+        }
+    } else if (u->session == AUDIO_SESSION_NOTIFICATION) {
+        if (__is_mute_policy()) {
+            route_flag |= AUDIO_ROUTE_FLAG_MUTE_POLICY;
+        }
+        else if (!__is_recording()) {
+            route_flag |= AUDIO_ROUTE_FLAG_DUAL_OUT;
+        }
+    } else if(u->session == AUDIO_SESSION_ALARM) {
+        if (!__is_recording()) {
+            route_flag |= AUDIO_ROUTE_FLAG_DUAL_OUT;
+        }
+    }
+    if (u->session == AUDIO_SESSION_VOICE_RECOGNITION) {
+        /* add flag if needed */
+    }
+
+    return route_flag;
+}
+#ifdef BURST_SHOT
+
+#define BURST_SOUND_DEFAULT_TIME_INTERVAL (0.09 * PA_USEC_PER_SEC)
+static void __play_audio_sample_timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata)
+{
+    struct userdata* u = (struct userdata*)userdata;
+    pa_usec_t interval = u->audio_sample_userdata.time_interval;
+    pa_usec_t now = 0ULL;
+
+    pa_assert(m);
+    pa_assert(e);
+    pa_assert(u);
+
+    pa_mutex_lock(u->audio_sample_userdata.mutex);
+
+    /* These checks are added to avoid server crashed on unpredictable situation*/
+    if ((u->audio_sample_userdata.time_event == NULL) ||
+       (u->audio_sample_userdata.i == NULL) ||
+       (u->audio_sample_userdata.q == NULL)) {
+        pa_log_error("Timer should not have fired with this condition time_event=%p i=%p q=%p",
+            u->audio_sample_userdata.time_event, u->audio_sample_userdata.i, u->audio_sample_userdata.q);
+
+        if (u->audio_sample_userdata.time_event != NULL) {
+            pa_core_rttime_restart(u->core, e, PA_USEC_INVALID);
+            u->core->mainloop->time_free(u->audio_sample_userdata.time_event);
+            u->audio_sample_userdata.time_event = NULL;
+        }
+        if (u->audio_sample_userdata.count > 1) {
+            if (u->audio_sample_userdata.i != NULL) {
+                pa_sink_input_set_mute(u->audio_sample_userdata.i, true, true);
+                pa_sink_input_unlink(u->audio_sample_userdata.i);
+            }
+            if (u->audio_sample_userdata.q != NULL) {
+                pa_memblockq_free(u->audio_sample_userdata.q);
+                u->audio_sample_userdata.q = NULL;
+            }
+        }
+        if (u->audio_sample_userdata.i != NULL) {
+            pa_sink_input_unref(u->audio_sample_userdata.i);
+            u->audio_sample_userdata.i = NULL;
+        }
+        u->audio_sample_userdata.is_running = false;
+    } else if (u->audio_sample_userdata.is_running) {
+        // calculate timer boosting
+        pa_log_info("- shot count = %d, memq len = %d ", u->audio_sample_userdata.count,
+                    pa_memblockq_get_length(u->audio_sample_userdata.q));
+        if (u->audio_sample_userdata.factor > 1ULL)
+            interval = u->audio_sample_userdata.time_interval / u->audio_sample_userdata.factor;
+
+        if (u->audio_sample_userdata.count == 0) {
+            // 5. first post data
+            pa_sink_input_put(u->audio_sample_userdata.i);
+        } else {
+            // 5. post data
+            if (pa_memblockq_push(u->audio_sample_userdata.q, &u->audio_sample_userdata.e->memchunk) < 0) {
+                pa_log_error("memory push fail cnt(%d), factor(%llu), interval(%llu)",
+                    u->audio_sample_userdata.count, u->audio_sample_userdata.factor, u->audio_sample_userdata.time_interval);
+                pa_assert(0);
+            }
+        }
+        u->audio_sample_userdata.count++;
+
+        pa_rtclock_now_args(&now);
+        pa_core_rttime_restart(u->core, e, now + interval);
+        if (u->audio_sample_userdata.factor > 1ULL)
+            u->audio_sample_userdata.factor -= 1ULL;
+    } else {
+        pa_core_rttime_restart(u->core, e, PA_USEC_INVALID);
+        u->core->mainloop->time_free(u->audio_sample_userdata.time_event);
+        u->audio_sample_userdata.time_event = NULL;
+
+        /* FIXME: How memblockq is freed when count is 1? */
+        // fading. but should be emitted first shutter sound totally.
+        if (u->audio_sample_userdata.count > 1) {
+            pa_sink_input_set_mute(u->audio_sample_userdata.i, true, true);
+            pa_sink_input_unlink(u->audio_sample_userdata.i);
+
+            pa_memblockq_free(u->audio_sample_userdata.q);
+            u->audio_sample_userdata.q = NULL;
+        }
+        pa_sink_input_unref(u->audio_sample_userdata.i);
+        u->audio_sample_userdata.i = NULL;
+        pa_log_info("sample shot clear!!");
+
+        /* Clear Burst vconf */
+        vconf_set_int (VCONF_SOUND_BURSTSHOT, 0);
+    }
+    pa_mutex_unlock(u->audio_sample_userdata.mutex);
+}
+
+static audio_return_t policy_play_sample_continuously(struct userdata *u, pa_native_connection *c, const char *name, pa_usec_t interval,
+    uint32_t volume_type, uint32_t gain_type, uint32_t volume_level, uint32_t *stream_idx)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    pa_proplist *p = 0;
+    pa_sink *sink = NULL;
+    audio_info_t audio_info;
+    double volume_linear = 1.0f;
+    pa_client *client = pa_native_connection_get_client(c);
+
+    pa_scache_entry *e;
+    pa_bool_t pass_volume = true;
+    pa_proplist *merged =0;
+    pa_sink_input *i = NULL;
+    pa_memblockq *q = NULL;
+    pa_memchunk silence;
+    pa_cvolume r;
+    pa_usec_t now = 0ULL;
+
+    if (!u->audio_sample_userdata.mutex)
+        u->audio_sample_userdata.mutex = pa_mutex_new(false, false);
+
+    pa_mutex_lock(u->audio_sample_userdata.mutex);
+
+    pa_assert(u->audio_sample_userdata.is_running == false); // allow one instace.
+
+    memset(&audio_info, 0x00, sizeof(audio_info_t));
+
+    p = pa_proplist_new();
+
+    /* Set volume type of stream */
+    pa_proplist_setf(p, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE, "%d", volume_type);
+    /* Set gain type of stream */
+    pa_proplist_setf(p, PA_PROP_MEDIA_TIZEN_GAIN_TYPE, "%d", gain_type);
+    /* Set policy */
+    pa_proplist_setf(p, PA_PROP_MEDIA_POLICY, "%s", volume_type == AUDIO_VOLUME_TYPE_FIXED ? POLICY_PHONE : POLICY_AUTO);
+
+    pa_proplist_update(p, PA_UPDATE_MERGE, client->proplist);
+
+    sink = pa_namereg_get_default_sink(u->core);
+
+    /* FIXME : Add gain_type parameter to API like volume_type */
+    audio_info.stream.gain_type = gain_type;
+
+    if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.get_volume_value(u->audio_mgr.data, &audio_info, volume_type, volume_level, &volume_linear)))) {
+        pa_log_warn("get_volume_value returns error:0x%x", audio_ret);
+        goto exit;
+    }
+
+   /*
+    1. load cam-shutter sample
+    2. create memchunk using sample.
+    3. create sink_input(cork mode)
+    4. set timer
+    5. post data(sink-input put or push memblockq)
+    */
+
+    //  1. load cam-shutter sample
+    merged = pa_proplist_new();
+
+    if (!(e = pa_namereg_get(u->core, name, PA_NAMEREG_SAMPLE)))
+        goto exit;
+
+    pa_proplist_sets(merged, PA_PROP_MEDIA_NAME, name);
+    pa_proplist_sets(merged, PA_PROP_EVENT_ID, name);
+    /* Set policy for selecting sink */
+    pa_proplist_sets(merged, PA_PROP_MEDIA_POLICY_IGNORE_PRESET_SINK, "yes");
+
+    if (e->lazy && !e->memchunk.memblock) {
+        pa_channel_map old_channel_map = e->channel_map;
+
+        if (pa_sound_file_load(u->core->mempool, e->filename, &e->sample_spec, &e->channel_map, &e->memchunk, merged) < 0)
+            goto exit;
+
+        pa_subscription_post(u->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
+
+        if (e->volume_is_set) {
+            if (pa_cvolume_valid(&e->volume))
+                pa_cvolume_remap(&e->volume, &old_channel_map, &e->channel_map);
+            else
+                pa_cvolume_reset(&e->volume, e->sample_spec.channels);
+        }
+    }
+
+    if (!e->memchunk.memblock)
+        goto exit;
+
+    if (e->volume_is_set && PA_VOLUME_IS_VALID(pa_sw_volume_from_linear(volume_linear))) {
+        pa_cvolume_set(&r, e->sample_spec.channels, pa_sw_volume_from_linear(volume_linear));
+        pa_sw_cvolume_multiply(&r, &r, &e->volume);
+    } else if (e->volume_is_set)
+        r = e->volume;
+    else if (PA_VOLUME_IS_VALID(pa_sw_volume_from_linear(volume_linear)))
+        pa_cvolume_set(&r, e->sample_spec.channels, pa_sw_volume_from_linear(volume_linear));
+    else
+        pass_volume = false;
+
+    pa_proplist_update(merged, PA_UPDATE_MERGE, e->proplist);
+    pa_proplist_update(p, PA_UPDATE_MERGE, merged);
+
+    if (e->lazy)
+        time(&e->last_used_time);
+
+    // 2. create memchunk using sample.
+    pa_silence_memchunk_get(&sink->core->silence_cache, sink->core->mempool, &silence, &e->sample_spec, 0);
+    q = pa_memblockq_new("pa_play_memchunk() q", 0, e->memchunk.length * 35, 0, &e->sample_spec, 1, 1, 0, &silence);
+    pa_memblock_unref(silence.memblock);
+
+    pa_assert_se(pa_memblockq_push(q, &e->memchunk) >= 0);
+
+    // 3. create sink_input(cork mode)
+    if (!(i = pa_memblockq_sink_input_new(sink, &e->sample_spec, &e->channel_map, q, pass_volume ? &r : NULL,
+        p, PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND)))
+        goto exit;
+
+    // 4. set timer
+    u->audio_sample_userdata.e = e;
+    u->audio_sample_userdata.i = i;
+    u->audio_sample_userdata.q = q;
+    u->audio_sample_userdata.time_interval = interval == (pa_usec_t)0 ? BURST_SOUND_DEFAULT_TIME_INTERVAL : interval;
+    u->audio_sample_userdata.is_running = true;
+    u->audio_sample_userdata.factor = 4ULL; // for memory block boosting
+    u->audio_sample_userdata.count = 0;
+
+    pa_rtclock_now_args(&now); // doesn't use arm barrel shiter. SBF
+    pa_log_warn("now(%llu), start interval(%llu)", now, interval / u->audio_sample_userdata.factor);
+    u->audio_sample_userdata.factor -= 1ULL;
+    u->audio_sample_userdata.time_event = pa_core_rttime_new(u->core, now, __play_audio_sample_timeout_cb, u);
+
+exit:
+    if (p)
+        pa_proplist_free(p);
+    if (merged)
+        pa_proplist_free(merged);
+    if (q && (u->audio_sample_userdata.is_running == false))
+        pa_memblockq_free(q);
+
+    pa_mutex_unlock(u->audio_sample_userdata.mutex);
+
+    return audio_ret;
+}
+
+static void  policy_stop_sample_continuously(struct userdata *u)
+{
+    if (u->audio_sample_userdata.time_event) {
+        pa_mutex_lock(u->audio_sample_userdata.mutex);
+        pa_assert(u->audio_sample_userdata.is_running);
+        u->audio_sample_userdata.is_running = false;
+        pa_mutex_unlock(u->audio_sample_userdata.mutex);
+        pa_log_info("timeout_cb called (%d) times", u->audio_sample_userdata.count);
+    }
+}
+
+#endif
+static audio_return_t policy_play_sample(struct userdata *u, pa_native_connection *c, const char *name, uint32_t volume_type, uint32_t gain_type, uint32_t volume_level, uint32_t *stream_idx)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    pa_proplist *p;
+    pa_sink *sink = NULL;
+    audio_info_t audio_info;
+    double volume_linear = 1.0f;
+    pa_client *client = pa_native_connection_get_client(c);
+    pa_bool_t is_boot_sound;
+    uint32_t sample_idx = 0;
+    char* booting = NULL;
+    const char* file_to_add = NULL;
+    int sample_ret = 0;
+
+    memset(&audio_info, 0x00, sizeof(audio_info_t));
+
+    p = pa_proplist_new();
+
+    /* Set volume type of stream */
+    pa_proplist_setf(p, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE, "%d", volume_type);
+    /* Set gain type of stream */
+    pa_proplist_setf(p, PA_PROP_MEDIA_TIZEN_GAIN_TYPE, "%d", gain_type);
+    /* Set policy */
+    pa_proplist_setf(p, PA_PROP_MEDIA_POLICY, "%s", volume_type == AUDIO_VOLUME_TYPE_FIXED ? POLICY_PHONE : POLICY_AUTO);
+
+    pa_proplist_update(p, PA_UPDATE_MERGE, client->proplist);
+
+    /* Set policy for selecting sink */
+    pa_proplist_sets(p, PA_PROP_MEDIA_POLICY_IGNORE_PRESET_SINK, "yes");
+    sink = pa_namereg_get_default_sink(u->core);
+
+    /* FIXME : Add gain_type parameter to API like volume_type */
+    audio_info.stream.gain_type = gain_type;
+
+    if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.get_volume_value(u->audio_mgr.data, &audio_info, volume_type, volume_level, &volume_linear)))) {
+        pa_log_warn("get_volume_value returns error:0x%x", audio_ret);
+        goto exit;
+    }
+
+    pa_log_debug("play_sample volume_type:%d gain_type:%d volume_linear:%f", volume_type, gain_type, volume_linear);
+
+    is_boot_sound = pa_streq(name, BOOTING_SOUND_SAMPLE);
+    if (is_boot_sound && pa_namereg_get(u->core, name, PA_NAMEREG_SAMPLE) == NULL) {
+        booting = vconf_get_str(VCONF_BOOTING);
+        file_to_add = (booting)? booting : (char *)DEFAULT_BOOTING_SOUND_PATH;
+        if ((sample_ret = pa_scache_add_file(u->core, name, file_to_add, &sample_idx)) != 0) {
+            pa_log_error("failed to add sample [%s][%s]", name, file_to_add);
+        } else {
+            pa_log_info("success to add sample [%s][%s]", name, file_to_add);
+        }
+        if (booting)
+            free(booting);
+    }
+
+    if (pa_scache_play_item(u->core, name, sink, pa_sw_volume_from_linear(volume_linear), p, stream_idx) < 0) {
+        pa_log_error("pa_scache_play_item fail");
+        audio_ret = AUDIO_ERR_UNDEFINED;
+        goto exit;
+    }
+
+    if (is_boot_sound && sample_ret == 0) {
+        if (pa_scache_remove_item(u->core, name) != 0) {
+            pa_log_error("failed to remove sample [%s]", name);
+        } else {
+            pa_log_info("success to remove sample [%s]", name);
+        }
+    }
+
+exit:
+    pa_proplist_free(p);
+
+    return audio_ret;
+}
+
+static audio_return_t policy_reset(struct userdata *u)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    pa_log_debug("reset");
+#if 0
+    __load_dump_config(u);
+#endif
+    if (u->audio_mgr.intf.reset) {
+        if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.reset(&u->audio_mgr.data)))) {
+            pa_log_error("audio_mgr reset failed");
+            return audio_ret;
+        }
+    }
+
+    return audio_ret;
+}
+
+static audio_return_t policy_set_session(struct userdata *u, uint32_t session, uint32_t start) {
+    uint32_t prev_session = u->session;
+    uint32_t prev_subsession = u->subsession;
+    pa_bool_t need_route = false;
+
+    pa_log_info("set_session:%s %s (current:%s,%s)",
+            __get_session_str(session), (start) ? "start" : "end", __get_session_str(u->session), __get_subsession_str(u->subsession));
+
+    if (start) {
+        u->session = session;
+
+        if ((u->session == AUDIO_SESSION_VOICECALL) || (u->session == AUDIO_SESSION_VIDEOCALL)) {
+            u->subsession = AUDIO_SUBSESSION_MEDIA;
+            u->call_muted = 0;
+        } else if (u->session == AUDIO_SESSION_VOIP) {
+            u->subsession = AUDIO_SUBSESSION_VOICE;
+        } else if (u->session == AUDIO_SESSION_VOICE_RECOGNITION) {
+            u->subsession = AUDIO_SUBSESSION_INIT;
+        } else {
+            u->subsession = AUDIO_SUBSESSION_NONE;
+        }
+        if (u->audio_mgr.intf.set_session) {
+            u->audio_mgr.intf.set_session(u->audio_mgr.data, session, u->subsession, AUDIO_SESSION_CMD_START);
+        }
+    } else {
+        if (u->audio_mgr.intf.set_session) {
+            u->audio_mgr.intf.set_session(u->audio_mgr.data, session, u->subsession, AUDIO_SESSION_CMD_END);
+        }
+        u->session = AUDIO_SESSION_MEDIA;
+        u->subsession = AUDIO_SUBSESSION_NONE;
+    }
+    if (prev_session != session) {
+        if ((session == AUDIO_SESSION_ALARM) || (session == AUDIO_SESSION_NOTIFICATION)) {
+            pa_log_info("switch route to dual output due to new session");
+            need_route = true;
+        } else if ((prev_session == AUDIO_SESSION_ALARM) || (prev_session == AUDIO_SESSION_NOTIFICATION)
+            || (((prev_session == AUDIO_SESSION_VOICECALL) || (prev_session == AUDIO_SESSION_VIDEOCALL)) && (prev_subsession == AUDIO_SUBSESSION_RINGTONE))) {
+            pa_log_info("switch route from dual output due to previous session");
+            need_route = true;
+        }
+    }
+
+
+    if (need_route) {
+        uint32_t route_flag = __get_route_flag(u);
+
+        if (u->audio_mgr.intf.set_route) {
+            u->audio_mgr.intf.set_route(u->audio_mgr.data, u->session, u->subsession, u->active_device_in, u->active_device_out, route_flag);
+        }
+        u->active_route_flag = route_flag;
+    } else {
+        /* route should be updated */
+        u->active_route_flag = (uint32_t)-1;
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t policy_set_subsession(struct userdata *u, uint32_t subsession, uint32_t subsession_opt) {
+    uint32_t prev_subsession = u->subsession;
+    pa_bool_t need_route = false;
+
+    pa_log_info("set_subsession:%s->%s opt:%x->%x (session:%s)",
+            __get_subsession_str(u->subsession), __get_subsession_str(subsession), u->subsession_opt, subsession_opt,
+            __get_session_str(u->session));
+
+    if (u->subsession == subsession && u->subsession_opt == subsession_opt) {
+        pa_log_debug("duplicated request is ignored subsession(%d) opt(0x%x)", subsession, subsession_opt);
+        return AUDIO_RET_OK;
+    }
+
+    u->subsession = subsession;
+#ifndef _TIZEN_PUBLIC_
+    if (u->subsession == AUDIO_SUBSESSION_VR_NORMAL || u->subsession == AUDIO_SUBSESSION_VR_DRIVE)
+        u->subsession_opt = subsession_opt;
+    else
+        u->subsession_opt = 0;
+#else
+    u->subsession_opt = subsession_opt;
+#endif
+
+    if (u->audio_mgr.intf.set_session) {
+        u->audio_mgr.intf.set_session(u->audio_mgr.data, u->session, u->subsession, AUDIO_SESSION_CMD_SUBSESSION);
+    }
+
+    if (prev_subsession!= subsession) {
+        if ((u->session == AUDIO_SESSION_VOICECALL) || (u->session == AUDIO_SESSION_VIDEOCALL)) {
+            if (subsession == AUDIO_SUBSESSION_RINGTONE) {
+                pa_log_info("switch route to dual output due to new subsession");
+                need_route = true;
+            } else if (prev_subsession == AUDIO_SUBSESSION_RINGTONE) {
+                pa_log_info("switch route from dual output due to previous subsession");
+                need_route = true;
+            }
+        }
+    }
+
+    if (need_route) {
+        uint32_t route_flag = __get_route_flag(u);
+
+        if (u->audio_mgr.intf.set_route) {
+            u->audio_mgr.intf.set_route(u->audio_mgr.data, u->session, u->subsession, u->active_device_in, u->active_device_out, route_flag);
+        }
+        u->active_route_flag = route_flag;
+    } else {
+        /* route should be updated */
+        u->active_route_flag = (uint32_t)-1;
+    }
+    return AUDIO_RET_OK;
+
+}
+static pa_bool_t pa_sink_input_get_mute(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+    pa_assert_ctl_context();
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
+
+    return i->muted;
+}
+static audio_return_t policy_set_active_device(struct userdata *u, uint32_t device_in, uint32_t device_out, uint32_t* need_update) {
+    pa_sink_input *si = NULL;
+    uint32_t idx;
+    uint32_t route_flag = 0;
+
+#ifndef TIZEN_MICRO
+    *need_update = true;
+#endif
+    route_flag = __get_route_flag(u);
+
+    pa_log_info("set_active_device session:%s,%s in:%s->%s out:%s->%s flag:%x->%x muteall:%d call_muted:%d",
+            __get_session_str(u->session), __get_subsession_str(u->subsession),
+            __get_device_in_str(u->active_device_in), __get_device_in_str(device_in),
+            __get_device_out_str(u->active_device_out), __get_device_out_str(device_out),
+            u->active_route_flag, route_flag, u->muteall, u->call_muted);
+
+    /* Skip duplicated request */
+    if ((device_in == AUDIO_DEVICE_IN_NONE || u->active_device_in == device_in) &&
+        (device_out == AUDIO_DEVICE_OUT_NONE || u->active_device_out == device_out) &&
+        u->active_route_flag == route_flag) {
+#ifdef TIZEN_MICRO
+        pa_log_debug("duplicated request is ignored device_in(%d) device_out(%d) flag(0x%x)", device_in, device_out, route_flag);
+#else
+        pa_log_debug("duplicated request is ignored device_in(%d) device_out(%d) flag(0x%x) need_update(%d)", device_in, device_out, route_flag, *need_update);
+#endif
+        return AUDIO_RET_OK;
+    }
+
+#ifdef TIZEN_MICRO
+    if (u->audio_mgr.intf.set_route) {
+        u->audio_mgr.intf.set_route(u->audio_mgr.data, u->session, u->subsession, device_in, device_out, route_flag);
+    }
+#else
+
+    /* skip volume changed callback */
+    if(u->active_device_out == device_out) {
+        *need_update = false;
+    }
+    if (u->audio_mgr.intf.set_route) {
+        audio_return_t audio_ret = AUDIO_RET_OK;
+        const char *device_switching_str;
+        uint32_t device_switching = 0;
+#ifdef PA_SLEEP_DURING_UCM
+        uint32_t need_sleep_for_ucm = 0;
+#endif
+
+        /* Mute sink inputs which are unmuted */
+        PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+            if ((device_switching_str = pa_proplist_gets(si->proplist, "module-policy.device_switching"))) {
+                pa_atou(device_switching_str, &device_switching);
+                if (device_switching) {
+                    if (AUDIO_IS_ERROR((audio_ret = policy_set_mute(u, si->index, (uint32_t)-1, AUDIO_DIRECTION_OUT, 1)))) {
+                        pa_log_warn("policy_set_mute(1) for stream[%d] returns error:0x%x", si->index, audio_ret);
+                    }
+#ifdef PA_SLEEP_DURING_UCM
+                    need_sleep_for_ucm = 1;
+#endif
+                }
+            }
+        }
+
+#ifdef PA_SLEEP_DURING_UCM
+        /* FIXME : sleep for ucm. Will enable if needed */
+        if (need_sleep_for_ucm) {
+            usleep(150000);
+        }
+#endif
+
+        u->audio_mgr.intf.set_route(u->audio_mgr.data, u->session, u->subsession, device_in, device_out, route_flag);
+        /* Unmute sink inputs which are muted due to device switching */
+        PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+            if ((device_switching_str = pa_proplist_gets(si->proplist, "module-policy.device_switching"))) {
+                pa_atou(device_switching_str, &device_switching);
+                if (device_switching) {
+                    pa_proplist_sets(si->proplist, "module-policy.device_switching", "0");
+                    if (AUDIO_IS_ERROR((audio_ret = __update_volume(u, si->index, (uint32_t)-1, (uint32_t)-1)))) {
+                        pa_log_warn("__update_volume for stream[%d] returns error:0x%x", si->index, audio_ret);
+                    }
+                    if (AUDIO_IS_ERROR((audio_ret = policy_set_mute(u, si->index, (uint32_t)-1, AUDIO_DIRECTION_OUT, 0)))) {
+                        pa_log_warn("policy_set_mute(0) for stream[%d] returns error:0x%x", si->index, audio_ret);
+                    }
+                }
+            }
+        }
+    }
+#endif
+
+    /* sleep for avoiding sound leak during UCM switching
+       this is just a workaround, we should synchronize in future */
+    if (device_out != AUDIO_DEVICE_OUT_NONE && u->active_device_out != device_out &&
+        u->session != AUDIO_SESSION_VOICECALL && u->session != AUDIO_SESSION_VIDEOCALL) {
+        /* Mute sink inputs which are unmuted */
+        PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+            if (!pa_sink_input_get_mute(si)) {
+                pa_proplist_sets(si->proplist, "module-policy.device_switching", "1");
+            }
+        }
+    }
+
+    /* Update active devices */
+    if (device_in != AUDIO_DEVICE_IN_NONE)
+        u->active_device_in = device_in;
+    if (device_out != AUDIO_DEVICE_OUT_NONE)
+        u->active_device_out = device_out;
+    u->active_route_flag = route_flag;
+
+    if (u->session == AUDIO_SESSION_VOICECALL) {
+        if (u->muteall) {
+            policy_set_mute(u, (-1), AUDIO_VOLUME_TYPE_CALL, AUDIO_DIRECTION_OUT, 1);
+        }
+        /* workaround for keeping call mute setting */
+        policy_set_mute(u, (-1), AUDIO_VOLUME_TYPE_CALL, AUDIO_DIRECTION_IN, u->call_muted);
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t policy_get_volume_level_max(struct userdata *u, uint32_t volume_type, uint32_t *volume_level) {
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    /* Call HAL function if exists */
+    if (u->audio_mgr.intf.get_volume_level_max) {
+        if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.get_volume_level_max(u->audio_mgr.data, volume_type, volume_level)))) {
+            pa_log_error("get_volume_level_max returns error:0x%x", audio_ret);
+            return audio_ret;
+        }
+    }
+    pa_log_info("get volume level max type:%d level:%d", volume_type, *volume_level);
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t __update_volume(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, uint32_t volume_level)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    pa_sink_input *si = NULL;
+    uint32_t idx;
+    audio_info_t audio_info;
+
+    pa_log_info("stream[%d], volume_type(%d), volume_level(%d)", stream_idx, volume_type, volume_level);
+
+    /* Update volume as current level if volume_level has -1 */
+    if (volume_level == (uint32_t)-1 && stream_idx != (uint32_t)-1) {
+        /* Skip updating if stream doesn't have volume type */
+        if (policy_get_volume_level(u, stream_idx, &volume_type, &volume_level) == AUDIO_ERR_UNDEFINED) {
+            return AUDIO_RET_OK;
+        }
+    }
+
+    if (u->muteall && (volume_type != AUDIO_VOLUME_TYPE_FIXED)) {
+        pa_log_debug("set_mute is called from __update_volume by muteall stream_idx:%d type:%d", stream_idx, volume_type);
+
+        if (policy_set_mute(u, stream_idx, volume_type, AUDIO_DIRECTION_OUT, 1) == AUDIO_RET_USE_HW_CONTROL) {
+            return AUDIO_RET_USE_HW_CONTROL;
+        }
+    }
+
+    /* Call HAL function if exists */
+    if (u->audio_mgr.intf.set_volume_level && (stream_idx == PA_INVALID_INDEX)) {
+        if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.set_volume_level(u->audio_mgr.data, NULL, volume_type, volume_level)))) {
+            pa_log_error("set_volume_level returns error:0x%x", audio_ret);
+            return audio_ret;
+        }
+    }
+
+    PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+
+        if (AUDIO_IS_ERROR(__fill_audio_playback_info(si, &audio_info))) {
+            /* skip mono sink-input */
+            continue;
+        }
+
+        /* Update volume of stream if it has requested volume type */
+        if ((stream_idx == idx) || ((stream_idx == PA_INVALID_INDEX) && (audio_info.stream.volume_type == volume_type))) {
+            double volume_linear = 1.0f;
+            pa_cvolume cv;
+
+            /* Call HAL function if exists */
+            if (u->audio_mgr.intf.set_volume_level) {
+                if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.set_volume_level(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, volume_level)))) {
+                    pa_log_error("set_volume_level for sink-input[%d] returns error:0x%x", idx, audio_ret);
+                    __free_audio_info(&audio_info);
+                    return audio_ret;
+                }
+            }
+
+            /* Get volume value by type & level */
+            if (u->audio_mgr.intf.get_volume_value && (audio_ret != AUDIO_RET_USE_HW_CONTROL)) {
+                if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.get_volume_value(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, volume_level, &volume_linear)))) {
+                    pa_log_warn("get_volume_value for sink-input[%d] returns error:0x%x", idx, audio_ret);
+                    __free_audio_info(&audio_info);
+                    return audio_ret;
+                }
+            }
+            pa_cvolume_set(&cv, si->sample_spec.channels, pa_sw_volume_from_linear(volume_linear));
+
+            pa_sink_input_set_volume(si, &cv, true, true);
+            if (idx == stream_idx) {
+                __free_audio_info(&audio_info);
+                break;
+            }
+        }
+        __free_audio_info(&audio_info);
+    }
+
+    return audio_ret;
+}
+
+static audio_return_t __update_volume_by_value(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, double* value)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    pa_sink_input *si = NULL;
+    uint32_t idx;
+    audio_info_t audio_info;
+
+    double volume = *value;
+    double gain = 1.0f;
+
+    PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+
+        if (AUDIO_IS_ERROR(__fill_audio_playback_info(si, &audio_info))) {
+            /* skip mono sink-input */
+            continue;
+        }
+
+        /* Update volume of stream if it has requested volume type */
+        if ((stream_idx == idx) || ((stream_idx == PA_INVALID_INDEX) && (audio_info.stream.volume_type == volume_type))) {
+            double volume_linear = 1.0f;
+            pa_cvolume cv;
+
+            // 1. get gain first
+            if (u->audio_mgr.intf.get_gain_value) {
+                if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.get_gain_value(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, &gain)))) {
+                    pa_log_warn("get_gain_value for sink-input[%d] volume_type(%d), returns error:0x%x", idx, audio_info.stream.volume_type, audio_ret);
+                    __free_audio_info(&audio_info);
+                    return audio_ret;
+                }
+            }
+
+            // 2. mul gain value
+            volume *= gain;
+
+            /* 3. adjust hw volume(LPA), Call HAL function if exists */
+            if (u->audio_mgr.intf.set_volume_value) {
+                if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.set_volume_value(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, &volume)))) {
+                    pa_log_error("set_volume_level for sink-input[%d] returns error:0x%x", idx, audio_ret);
+                    __free_audio_info(&audio_info);
+                    return audio_ret;
+                }
+            }
+
+            // 4. adjust sw volume.
+            if(audio_ret != AUDIO_RET_USE_HW_CONTROL)
+                pa_cvolume_set(&cv, si->sample_spec.channels, pa_sw_volume_from_linear(volume));
+            else
+                pa_cvolume_set(&cv, si->sample_spec.channels, pa_sw_volume_from_linear(volume_linear));
+
+            pa_sink_input_set_volume(si, &cv, true, true);
+
+            if (idx == stream_idx) {
+                __free_audio_info(&audio_info);
+                break;
+            }
+        }
+        __free_audio_info(&audio_info);
+    }
+
+    return audio_ret;
+}
+
+#ifdef PRIMARY_VOLUME
+static int __set_primary_volume(struct userdata *u, void* key, int volumetype, int is_new)
+{
+    const int NO_INSTANCE = -1;
+    const int CAPURE_ONLY = -2; // check mm_sound.c
+
+    int ret = -1;
+    int default_primary_vol = NO_INSTANCE;
+    int default_primary_vol_prio = NO_INSTANCE;
+
+    struct pa_primary_volume_type_info* p_volume = NULL;
+    struct pa_primary_volume_type_info* n_p_volume = NULL;
+    struct pa_primary_volume_type_info* new_volume = NULL;
+
+    // descending order
+    int priority[] = {
+        AUDIO_PRIMARY_VOLUME_TYPE_SYSTEM,
+        AUDIO_PRIMARY_VOLUME_TYPE_NOTIFICATION,
+        AUDIO_PRIMARY_VOLUME_TYPE_ALARM,
+        AUDIO_PRIMARY_VOLUME_TYPE_RINGTONE,
+        AUDIO_PRIMARY_VOLUME_TYPE_MEDIA,
+        AUDIO_PRIMARY_VOLUME_TYPE_VOICE,
+        AUDIO_PRIMARY_VOLUME_TYPE_CALL,
+        AUDIO_PRIMARY_VOLUME_TYPE_VOIP,
+        AUDIO_PRIMARY_VOLUME_TYPE_FIXED,
+        AUDIO_PRIMARY_VOLUME_TYPE_MAX // for capture handle
+    };
+
+    if(is_new) {
+        new_volume = pa_xnew0(struct pa_primary_volume_type_info, 1);
+        new_volume->key = key;
+        new_volume->volumetype = volumetype;
+        new_volume->priority = priority[volumetype];
+
+        // no items.
+        if(u->primary_volume == NULL) {
+            PA_LLIST_PREPEND(struct pa_primary_volume_type_info, u->primary_volume, new_volume);
+        } else {
+            // already added
+            PA_LLIST_FOREACH_SAFE(p_volume, n_p_volume, u->primary_volume) {
+                if(p_volume->key == key) {
+                    ret = 0;
+                    pa_xfree(new_volume);
+                    goto exit;
+                }
+            }
+
+            // add item.
+            PA_LLIST_FOREACH_SAFE(p_volume, n_p_volume, u->primary_volume) {
+                if(p_volume->priority <= priority[volumetype]) {
+                    PA_LLIST_INSERT_AFTER(struct pa_primary_volume_type_info, u->primary_volume, p_volume, new_volume);
+                    break;
+                } else if(p_volume->priority > priority[volumetype]) {
+                    PA_LLIST_PREPEND(struct pa_primary_volume_type_info, u->primary_volume, new_volume);
+                    break;
+                }
+            }
+        }
+        pa_log_info("add volume data to primary volume list. volumetype(%d), priority(%d)", new_volume->volumetype, new_volume->priority);
+    } else { // remove(unlink)
+        PA_LLIST_FOREACH_SAFE(p_volume, n_p_volume, u->primary_volume) {
+            if(p_volume->key == key) {
+                PA_LLIST_REMOVE(struct pa_primary_volume_type_info, u->primary_volume, p_volume);
+                pa_log_info("remove volume data from primary volume list. volumetype(%d), priority(%d)", p_volume->volumetype, p_volume->priority);
+                pa_xfree(p_volume);
+                break;
+            }
+        }
+    }
+
+    if(u->primary_volume) {
+        if(u->primary_volume->volumetype == AUDIO_PRIMARY_VOLUME_TYPE_MAX) {
+            default_primary_vol = CAPURE_ONLY;
+            default_primary_vol_prio = CAPURE_ONLY;
+        } else {
+            default_primary_vol = u->primary_volume->volumetype;
+            default_primary_vol_prio = u->primary_volume->priority;
+        }
+    }
+    pa_log_info("current primary volumetype(%d), priority(%d)", default_primary_vol, default_primary_vol_prio);
+
+    if(vconf_set_int(VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE, default_primary_vol) < 0) {
+        ret = -1;
+        pa_log_info("VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE set failed default_primary_vol(%d)", default_primary_vol);
+    }
+
+exit:
+
+    return ret;
+}
+#endif
+
+
+static audio_return_t policy_get_volume_level(struct userdata *u, uint32_t stream_idx, uint32_t *volume_type, uint32_t *volume_level) {
+    pa_sink_input *si = NULL;
+    const char *si_volume_type_str;
+
+    if (*volume_type == (uint32_t)-1 && stream_idx != (uint32_t)-1) {
+        if ((si = pa_idxset_get_by_index(u->core->sink_inputs, stream_idx))) {
+            if ((si_volume_type_str = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
+                pa_atou(si_volume_type_str, volume_type);
+            } else {
+                pa_log_debug("stream[%d] doesn't have volume type", stream_idx);
+                return AUDIO_ERR_UNDEFINED;
+            }
+        } else {
+            pa_log_warn("stream[%d] doesn't exist", stream_idx);
+            return AUDIO_ERR_PARAMETER;
+        }
+    }
+
+    if (*volume_type >= AUDIO_VOLUME_TYPE_MAX) {
+        pa_log_warn("volume_type (%d) invalid", *volume_type);
+        return AUDIO_ERR_PARAMETER;
+    }
+    if (u->audio_mgr.intf.get_volume_level) {
+        u->audio_mgr.intf.get_volume_level(u->audio_mgr.data, *volume_type, volume_level);
+    }
+
+    pa_log_info("get_volume_level stream_idx:%d type:%d level:%d", stream_idx, *volume_type, *volume_level);
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t policy_get_volume_value(struct userdata *u, uint32_t stream_idx, uint32_t *volume_type, uint32_t *volume_level, double* volume_linear) {
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_info_t audio_info;
+    pa_sink_input *si = NULL;
+
+    *volume_linear = 1.0f;
+
+    si = pa_idxset_get_by_index(u->core->sink_inputs, stream_idx);
+    if (si != NULL) {
+        if (AUDIO_IS_ERROR(__fill_audio_playback_info(si, &audio_info))) {
+            pa_log_debug("fill info failed. stream_idx[%d]", stream_idx);
+            return AUDIO_ERR_UNDEFINED;
+        }
+
+        if(u->audio_mgr.intf.get_volume_value) {
+            if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.get_volume_value(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, *volume_level, volume_linear)))) {
+                pa_log_warn("get_volume_value for stream_idx[%d] returns error:0x%x", stream_idx, audio_ret);
+                return audio_ret;
+            }
+        }
+        __free_audio_info(&audio_info);
+   }
+    return audio_ret;
+}
+
+static audio_return_t policy_set_volume_level(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, uint32_t volume_level) {
+
+    pa_log_info("set_volume_level stream_idx:%d type:%d level:%d", stream_idx, volume_type, volume_level);
+
+    /* Store volume level of type */
+    if (volume_type != (uint32_t)-1) {
+        if (u->audio_mgr.intf.set_volume_level) {
+            u->audio_mgr.intf.set_volume_level(u->audio_mgr.data, NULL, volume_type, volume_level);
+        }
+    }
+
+    return __update_volume(u, stream_idx, volume_type, volume_level);
+}
+
+static audio_return_t policy_set_volume_value(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, double* value) {
+
+    pa_log_info("set_volume_value stream_idx:%d type:%d value:%f", stream_idx, volume_type, *value);
+
+    return __update_volume_by_value(u, stream_idx, volume_type, value);
+}
+
+static audio_return_t policy_update_volume(struct userdata *u) {
+    uint32_t volume_type;
+    uint32_t volume_level = 0;
+
+    pa_log_info("update_volume");
+
+    for (volume_type = 0; volume_type < AUDIO_VOLUME_TYPE_MAX; volume_type++) {
+        if (u->audio_mgr.intf.get_volume_level) {
+            u->audio_mgr.intf.get_volume_level(u->audio_mgr.data, volume_type, &volume_level);
+        }
+        __update_volume(u, (uint32_t)-1, volume_type, volume_level);
+#ifdef WEARABLE_FIX // commit : update call mute status after changing audio pathupdate call mute status after changing audio path
+        /* workaround for updating call mute after setting call path */
+        if (u->session == AUDIO_SESSION_VOICECALL) {
+            uint32_t call_muted = 0;
+
+            if (u->audio_mgr.intf.get_mute) {
+                u->audio_mgr.intf.get_mute(u->audio_mgr.data, NULL, AUDIO_VOLUME_TYPE_CALL, AUDIO_DIRECTION_IN, &call_muted);
+                if (u->call_muted != (int)call_muted && u->audio_mgr.intf.set_mute) {
+                    u->audio_mgr.intf.set_mute(u->audio_mgr.data, NULL, AUDIO_VOLUME_TYPE_CALL, AUDIO_DIRECTION_IN, u->call_muted);
+                }
+            }
+        }
+#endif
+    }
+
+    return AUDIO_RET_OK;
+}
+
+static audio_return_t policy_get_mute(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, uint32_t direction, uint32_t *mute) {
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    pa_sink_input *si = NULL;
+    uint32_t idx;
+    audio_info_t audio_info;
+
+    if (u->audio_mgr.intf.get_mute && (stream_idx == PA_INVALID_INDEX)) {
+        audio_ret = u->audio_mgr.intf.get_mute(u->audio_mgr.data, NULL, volume_type, direction, mute);
+        if (audio_ret == AUDIO_RET_USE_HW_CONTROL) {
+            return audio_ret;
+        } else {
+            pa_log_error("get_mute returns error:0x%x", audio_ret);
+            return audio_ret;
+        }
+    }
+
+    if (direction == AUDIO_DIRECTION_OUT) {
+        PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+            if (AUDIO_IS_ERROR(__fill_audio_playback_info(si, &audio_info))) {
+                /* skip mono sink-input */
+                continue;
+            }
+
+            /* Update mute of stream if it has requested stream or volume type */
+            if ((stream_idx == idx) || ((stream_idx == PA_INVALID_INDEX) && (audio_info.stream.volume_type == volume_type))) {
+
+                /* Call HAL function if exists */
+                if (u->audio_mgr.intf.get_mute) {
+                    audio_ret = u->audio_mgr.intf.get_mute(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, direction, mute);
+                    if (audio_ret == AUDIO_RET_USE_HW_CONTROL) {
+                        return audio_ret;
+                    } else if (AUDIO_IS_ERROR(audio_ret)) {
+                        pa_log_error("get_mute for sink-input[%d] returns error:0x%x", idx, audio_ret);
+                        return audio_ret;
+                    }
+                }
+
+                *mute = (uint32_t)pa_sink_input_get_mute(si);
+                break;
+            }
+            __free_audio_info(&audio_info);
+        }
+    }
+
+    pa_log_info("get mute stream_idx:%d type:%d direction:%d mute:%d", stream_idx, volume_type, direction, *mute);
+    return audio_ret;
+}
+
+static audio_return_t policy_set_mute(struct userdata *u, uint32_t stream_idx, uint32_t volume_type, uint32_t direction, uint32_t mute) {
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    pa_sink_input *si = NULL;
+    uint32_t idx;
+    audio_info_t audio_info;
+    const char *si_volume_type_str;
+
+    pa_log_info("set_mute stream_idx:%d type:%d direction:%d mute:%d", stream_idx, volume_type, direction, mute);
+
+    if (volume_type == (uint32_t)-1 && stream_idx != (uint32_t)-1) {
+        if ((si = pa_idxset_get_by_index(u->core->sink_inputs, stream_idx))) {
+            if ((si_volume_type_str = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
+                pa_atou(si_volume_type_str, &volume_type);
+            } else {
+                pa_log_debug("stream[%d] doesn't have volume type", stream_idx);
+                return AUDIO_ERR_UNDEFINED;
+            }
+        } else {
+            pa_log_warn("stream[%d] doesn't exist", stream_idx);
+            return AUDIO_ERR_PARAMETER;
+        }
+    }
+
+    /* workaround for keeping call mute setting */
+    if ((volume_type == AUDIO_VOLUME_TYPE_CALL) && (direction == AUDIO_DIRECTION_IN)) {
+        u->call_muted = mute;
+    }
 
-static bool policy_is_filter (pa_sink_input* si)
-{
-       const char* role = NULL;
+    if (u->muteall && !mute && (direction == AUDIO_DIRECTION_OUT) && (volume_type != AUDIO_VOLUME_TYPE_FIXED)) {
+        pa_log_info("set_mute is ignored by muteall");
+        return audio_ret;
+    }
 
-       if (si == NULL) {
-               pa_log_warn ("input param sink-input is null");
-               return false;
-       }
+    /* Call HAL function if exists */
+    if (u->audio_mgr.intf.set_mute && (stream_idx == PA_INVALID_INDEX)) {
+        audio_ret = u->audio_mgr.intf.set_mute(u->audio_mgr.data, NULL, volume_type, direction, mute);
+        if (audio_ret == AUDIO_RET_USE_HW_CONTROL) {
+            pa_log_info("set_mute(call) returns error:0x%x mute:%d", audio_ret, mute);
+            return audio_ret;
+        } else if (AUDIO_IS_ERROR(audio_ret)) {
+            pa_log_error("set_mute returns error:0x%x", audio_ret);
+            return audio_ret;
+        }
+    }
 
-       if ((role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE))) {
-#ifdef DEBUG_DETAIL
-               pa_log_debug("[POLICY][%s] Role of sink input [%d] = %s", __func__, si->index, role);
-#endif
-               if (pa_streq(role, "filter")) {
-#ifdef DEBUG_DETAIL
-                       pa_log_debug("[POLICY] no need to change of sink for %s", role);
-#endif
-                       return true;
-               }
-       }
+    if (direction == AUDIO_DIRECTION_OUT) {
+        PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+            if (AUDIO_IS_ERROR(__fill_audio_playback_info(si, &audio_info))) {
+                /* skip mono sink-input */
+                continue;
+            }
+
+            /* Update mute of stream if it has requested stream or volume type */
+            if ((stream_idx == idx) || ((stream_idx == PA_INVALID_INDEX) && (audio_info.stream.volume_type == volume_type))) {
+
+                /* Call HAL function if exists */
+                if (u->audio_mgr.intf.set_mute) {
+                    audio_ret = u->audio_mgr.intf.set_mute(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, direction, mute);
+                    if (AUDIO_IS_ERROR(audio_ret)) {
+                        pa_log_error("set_mute for sink-input[%d] returns error:0x%x", idx, audio_ret);
+                        return audio_ret;
+                    }
+                }
+
+                pa_sink_input_set_mute(si, (pa_bool_t)mute, true);
+                if (idx == stream_idx)
+                    break;
+            }
+            __free_audio_info(&audio_info);
+        }
+    }
 
-       return false;
+    return audio_ret;
 }
 
+static pa_bool_t policy_is_available_high_latency(struct userdata *u)
+{
+    pa_sink_input *si = NULL;
+    uint32_t idx;
+    const char *si_policy_str;
+
+    PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+        if ((si_policy_str = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_POLICY))) {
+            if (pa_streq(si_policy_str, POLICY_HIGH_LATENCY) && sink_is_highlatency(si->sink)) {
+                pa_log_info("high latency is exists");
+                return false;
+            }
+        }
+    }
 
+    return true;
+}
 
 #define EXT_VERSION 1
 
@@ -346,7 +2817,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
                        pa_log_debug("[POLICY] Policy of sink input [%d] = %s", si->index, policy);
 
                        /* Select sink to move and move to it */
-                       sink_to_move = policy_select_proper_sink (u->core, policy, u->is_mono);
+                       sink_to_move = policy_select_proper_sink (u, policy, si, u->is_mono);
                        if (sink_to_move) {
                                pa_log_debug("[POLICY][%s] Moving sink-input[%d] from [%s] to [%s]", __func__, si->index, si->sink->name, sink_to_move->name);
                                pa_sink_input_move_to(si, sink_to_move, false);
@@ -386,8 +2857,276 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
                break;
        }
 
-    default:
-      goto fail;
+   case SUBCOMMAND_PLAY_SAMPLE: {
+            const char *name;
+            uint32_t volume_type = 0;
+            uint32_t gain_type = 0;
+            uint32_t volume_level = 0;
+            uint32_t stream_idx = PA_INVALID_INDEX;
+
+            if (pa_tagstruct_gets(t, &name) < 0 ||
+                pa_tagstruct_getu32(t, &volume_type) < 0 ||
+                pa_tagstruct_getu32(t, &gain_type) < 0 ||
+                pa_tagstruct_getu32(t, &volume_level) < 0 ||
+                !pa_tagstruct_eof(t)) {
+                pa_log_error("protocol error");
+                goto fail;
+            }
+
+            policy_play_sample(u, c, name, volume_type, gain_type, volume_level, &stream_idx);
+
+            pa_tagstruct_putu32(reply, stream_idx);
+            break;
+        }
+#ifdef BURST_SHOT
+
+        case SUBCOMMAND_PLAY_SAMPLE_CONTINUOUSLY: {
+            const char *name;
+            pa_bool_t start;
+            uint32_t volume_type = 0;
+            uint32_t gain_type = 0;
+            uint32_t volume_level = 0;
+            uint32_t stream_idx = PA_INVALID_INDEX;
+            pa_usec_t interval;
+
+            if (pa_tagstruct_gets(t, &name) < 0 ||
+                pa_tagstruct_get_boolean(t, &start) < 0 ||
+                pa_tagstruct_getu32(t, &volume_type) < 0 ||
+                pa_tagstruct_getu32(t, &gain_type) < 0 ||
+                pa_tagstruct_getu32(t, &volume_level) < 0 ||
+                pa_tagstruct_get_usec(t, &interval) < 0 ||
+                !pa_tagstruct_eof(t)) {
+                pa_log_error("protocol error");
+                goto fail;
+            }
+            /*When play sample continuous is in running state another instance is not allowed*/
+            if (start == true) {
+                if (u->audio_sample_userdata.is_running == false) {
+                    /* Now it is time to prepare burstshot...set burstshot vconf */
+                    vconf_set_int (VCONF_SOUND_BURSTSHOT, 1);
+
+                    pa_log_warn("play_sample_continuously start. name(%s), vol_type(%d), gain_type(%d), vol_level(%d), interval(%lu ms)",
+                        name, volume_type, gain_type, volume_level, (unsigned long) (interval / PA_USEC_PER_MSEC));
+                    policy_play_sample_continuously(u, c, name, interval, volume_type, gain_type, volume_level, &stream_idx);
+
+                    /* Running false after start means, start failed....unset burstshot vconf */
+                    if (u->audio_sample_userdata.is_running == false) {
+                        vconf_set_int (VCONF_SOUND_BURSTSHOT, 0);
+                    }
+                } else {
+                    pa_log_warn("play_sample_continuously is in running state - do nothing");
+                }
+            } else if ((start == false) && (u->audio_sample_userdata.is_running == true)) {
+                pa_log_warn("play_sample_continuously end.");
+                policy_stop_sample_continuously(u);
+            } else {
+                pa_log_error("play sample continuously unknown command. name(%s), start(%d)", name, start);
+            }
+
+            pa_tagstruct_putu32(reply, stream_idx);
+            break;
+        }
+
+#endif
+        case SUBCOMMAND_MUTEALL: {
+            const char *si_gain_type_str;
+            pa_bool_t enable;
+            unsigned i;
+            uint32_t gain_type;
+#if 0
+            pa_cvolume cvol ;
+            pa_cvolume* scvol ;
+#endif
+
+            if (pa_tagstruct_get_boolean(t, &enable) < 0)
+                goto fail;
+
+            pa_log_debug ("new muteall value = %d\n", enable);
+            if (enable == u->muteall) {
+                pa_log_debug ("No changes in muteall value = %d", u->muteall);
+                break;
+            }
+
+            u->muteall = enable;
+
+/* Use mute instead of volume for muteall */
+#if 1
+#ifdef TIZEM_MICRO
+            /* Special case. Set mute for call volume type in B3. */
+            policy_set_mute(u, (-1), AUDIO_VOLUME_TYPE_CALL, AUDIO_DIRECTION_OUT, u->muteall);
+#else
+            for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) {
+                policy_set_mute(u, (-1), i, AUDIO_DIRECTION_OUT, u->muteall);
+            }
+#endif
+            PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+                /* Skip booting sound for power off mute streams policy. */
+                if (u->muteall && (si_gain_type_str = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_TIZEN_GAIN_TYPE))) {
+                    pa_atou(si_gain_type_str, &gain_type);
+                    if (gain_type == AUDIO_GAIN_TYPE_BOOTING)
+                        continue;
+                }
+                pa_sink_input_set_mute(si, u->muteall, true);
+            }
+#else
+            /* Apply new volume  value to each Sink_input */
+            if (u->muteall) {
+                PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+                    scvol = pa_sink_input_get_volume (si, &cvol,true);
+                    for (i = 0; i < scvol->channels; i++) {
+                        scvol->values[i] = 0;
+                    }
+                    pa_sink_input_set_volume(si,scvol,true,true);
+                }
+            } else {
+                PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+                    if (pa_streq(si->module->name,"module-remap-sink")) {
+                        scvol = pa_sink_input_get_volume (si, &cvol,true);
+                        for (i = 0; i < scvol->channels; i++) {
+                            scvol->values[i] = MAX_VOLUME_FOR_MONO;
+                        }
+                        pa_sink_input_set_volume(si,scvol,true,true);
+                    }
+                }
+            }
+#endif
+            break;
+        }
+
+        case SUBCOMMAND_SET_USE_CASE: {
+            break;
+        }
+
+        case SUBCOMMAND_SET_SESSION: {
+            uint32_t session = 0;
+            uint32_t start = 0;
+
+            pa_tagstruct_getu32(t, &session);
+            pa_tagstruct_getu32(t, &start);
+
+            policy_set_session(u, session, start);
+            break;
+        }
+
+        case SUBCOMMAND_SET_SUBSESSION: {
+            uint32_t subsession = 0;
+            uint32_t subsession_opt = 0;
+
+            pa_tagstruct_getu32(t, &subsession);
+            pa_tagstruct_getu32(t, &subsession_opt);
+
+            policy_set_subsession(u, subsession, subsession_opt);
+            break;
+        }
+
+        case SUBCOMMAND_SET_ACTIVE_DEVICE: {
+            uint32_t device_in = 0;
+            uint32_t device_out = 0;
+            uint32_t need_update = false;
+
+            pa_tagstruct_getu32(t, &device_in);
+            pa_tagstruct_getu32(t, &device_out);
+
+            policy_set_active_device(u, device_in, device_out, &need_update);
+            pa_tagstruct_putu32(reply, need_update);
+            break;
+        }
+
+        case SUBCOMMAND_RESET: {
+
+            policy_reset(u);
+
+            break;
+        }
+
+        case SUBCOMMAND_GET_VOLUME_LEVEL_MAX: {
+            uint32_t volume_type = 0;
+            uint32_t volume_level = 0;
+
+            pa_tagstruct_getu32(t, &volume_type);
+
+            policy_get_volume_level_max(u, volume_type, &volume_level);
+
+            pa_tagstruct_putu32(reply, volume_level);
+            break;
+        }
+
+        case SUBCOMMAND_GET_VOLUME_LEVEL: {
+            uint32_t stream_idx = PA_INVALID_INDEX;
+            uint32_t volume_type = 0;
+            uint32_t volume_level = 0;
+
+            pa_tagstruct_getu32(t, &stream_idx);
+            pa_tagstruct_getu32(t, &volume_type);
+
+            policy_get_volume_level(u, stream_idx, &volume_type, &volume_level);
+
+            pa_tagstruct_putu32(reply, volume_level);
+            break;
+        }
+
+        case SUBCOMMAND_SET_VOLUME_LEVEL: {
+            uint32_t stream_idx = PA_INVALID_INDEX;
+            uint32_t volume_type = 0;
+            uint32_t volume_level = 0;
+
+            pa_tagstruct_getu32(t, &stream_idx);
+            pa_tagstruct_getu32(t, &volume_type);
+            pa_tagstruct_getu32(t, &volume_level);
+
+            policy_set_volume_level(u, stream_idx, volume_type, volume_level);
+            break;
+        }
+
+        case SUBCOMMAND_UPDATE_VOLUME: {
+            policy_update_volume(u);
+            break;
+        }
+
+        case SUBCOMMAND_GET_MUTE: {
+            uint32_t stream_idx = PA_INVALID_INDEX;
+            uint32_t volume_type = 0;
+            uint32_t direction = 0;
+            uint32_t mute = 0;
+
+            pa_tagstruct_getu32(t, &stream_idx);
+            pa_tagstruct_getu32(t, &volume_type);
+            pa_tagstruct_getu32(t, &direction);
+
+            policy_get_mute(u, stream_idx, volume_type, direction, &mute);
+
+            pa_tagstruct_putu32(reply, mute);
+            break;
+        }
+
+        case SUBCOMMAND_SET_MUTE: {
+            uint32_t stream_idx = PA_INVALID_INDEX;
+            uint32_t volume_type = 0;
+            uint32_t direction = 0;
+            uint32_t mute = 0;
+
+            pa_tagstruct_getu32(t, &stream_idx);
+            pa_tagstruct_getu32(t, &volume_type);
+            pa_tagstruct_getu32(t, &direction);
+            pa_tagstruct_getu32(t, &mute);
+
+            policy_set_mute(u, stream_idx, volume_type, direction, mute);
+            break;
+        }
+        case SUBCOMMAND_IS_AVAILABLE_HIGH_LATENCY: {
+            pa_bool_t available = false;
+
+            available = policy_is_available_high_latency(u);
+
+            pa_tagstruct_putu32(reply, (uint32_t)available);
+            break;
+        }
+        case SUBCOMMAND_UNLOAD_HDMI: {
+            break;
+        }
+
+        default:
+            goto fail;
   }
 
   pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
@@ -400,53 +3139,206 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
 
   return -1;
 }
+static void __set_sink_input_role_type(pa_proplist *p, int gain_type)
+{
+    const char* role = NULL;
+
+    if ((role = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE))) {
+        /* "solo" has priority over other roles */
+        if (pa_streq(role, "solo")) {
+            pa_log_info("already set role to [%s]", role);
+            return;
+        } else {
+            if(gain_type == AUDIO_GAIN_TYPE_SHUTTER1 || gain_type == AUDIO_GAIN_TYPE_SHUTTER2)
+                role = "camera";
+            else
+                role = "normal";
+        }
+    } else {
+        role = "normal";
+    }
+    pa_proplist_sets (p, PA_PROP_MEDIA_ROLE, role);
+    pa_log_info("set role [%s]", role);
 
+    return;
+}
 /*  Called when new sink-input is creating  */
 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u)
 {
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_info_t audio_info;
     const char *policy = NULL;
+    const char *ignore_preset_sink = NULL;
+    const char *master_name = NULL;
+    pa_sink *realsink = NULL;
+    uint32_t volume_level = 0;
+    pa_strbuf *s = NULL;
+    const char *rate_str = NULL;
+    const char *ch_str = NULL;
+    char *s_info = NULL;
 
     pa_assert(c);
     pa_assert(new_data);
     pa_assert(u);
 
     if (!new_data->proplist) {
-        pa_log_debug("[POLICY] New stream lacks property data.");
-        return PA_HOOK_OK;
-    }
-
-    /* If sink-input has already sink, skip */
-    if (new_data->sink) {
-       /* sink-input with filter role will be also here because sink is already set */
-#ifdef DEBUG_DETAIL
-        pa_log_debug("[POLICY] Not setting device for stream [%s], because already set.",
-                       pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
-#endif
+        pa_log_debug(" New stream lacks property data.");
         return PA_HOOK_OK;
     }
 
     /* If no policy exists, skip */
     if (!(policy = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_POLICY))) {
-        pa_log_debug("[POLICY][%s] Not setting device for stream [%s], because it lacks policy.",
-                       __func__, pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
+        pa_log_debug("Not setting device for stream [%s], because it lacks policy.",
+                pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
         return PA_HOOK_OK;
     }
-    pa_log_debug("[POLICY][%s] Policy for stream [%s] = [%s]",
-               __func__, pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)), policy);
 
-    /* Set proper sink to sink-input */
-    pa_sink* new_sink = policy_select_proper_sink(c, policy, u->is_mono);
+    /* Parse request formats for samplerate & channel infomation */
+    if (new_data->req_formats) {
+        pa_format_info* req_format = pa_idxset_first(new_data->req_formats, NULL);
+        if (req_format && req_format->plist) {
+            rate_str = pa_proplist_gets(req_format->plist, PA_PROP_FORMAT_RATE);
+            ch_str = pa_proplist_gets(req_format->plist, PA_PROP_FORMAT_CHANNELS);
+            pa_log_info("req rate = %s, req ch = %s", rate_str, ch_str);
+
+            if (ch_str)
+                new_data->sample_spec.channels = atoi (ch_str);
+            if (rate_str)
+                new_data->sample_spec.rate = atoi (rate_str);
+        }
+    } else {
+        pa_log_debug("no request formats available");
+    }
+
+    /* Check if this input want to be played via the sink selected by module-policy */
+    if ((ignore_preset_sink = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_POLICY_IGNORE_PRESET_SINK))) {
+        pa_log_debug("ignore_preset_sink is enabled. module-policy will judge a proper sink for stream [%s]",
+                pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
+    } else {
+        ignore_preset_sink = "no";
+    }
+
+    /* If sink-input has already sink, skip */
+    if (new_data->sink && (strncmp("yes", ignore_preset_sink, strlen("yes")))) {
+        /* sink-input with filter role will be also here because sink is already set */
+#ifdef DEBUG_DETAIL
+        pa_log_debug(" Not setting device for stream [%s], because already set.",
+                pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
+#endif
+    } else {
+       
+       /* Set proper sink to sink-input */
+    pa_sink* new_sink = policy_select_proper_sink(u, policy, NULL, u->is_mono);
     if(new_sink != new_data->sink)
-    {
         pa_sink_input_new_data_set_sink(new_data, new_sink, false);
     }
-       /*new_data->save_sink = false;
-       new_data->sink = policy_select_proper_sink (c, policy, u->is_mono);*/
-       pa_log_debug("[POLICY][%s] set sink of sink-input to [%s]", __func__, (new_data->sink)? new_data->sink->name : "null");
+
+    s = pa_strbuf_new();
+    master_name = pa_proplist_gets(new_data->sink->proplist, PA_PROP_DEVICE_MASTER_DEVICE);
+    if (master_name)
+        realsink = pa_namereg_get(c, master_name, PA_NAMEREG_SINK);
+
+    if (AUDIO_IS_ERROR((audio_ret = __fill_audio_playback_stream_info(new_data->proplist, &new_data->sample_spec, &audio_info)))) {
+        pa_log_debug("__fill_audio_playback_stream_info returns 0x%x", audio_ret);
+    } else if (AUDIO_IS_ERROR((audio_ret = __fill_audio_playback_device_info(realsink? realsink->proplist : new_data->sink->proplist, &audio_info)))) {
+        pa_log_debug("__fill_audio_playback_device_info returns 0x%x", audio_ret);
+    } else {
+        double volume_linear = 1.0f;
+
+        // set role type
+        __set_sink_input_role_type(new_data->proplist, audio_info.stream.gain_type);
+
+        if (u->audio_mgr.intf.get_volume_level) {
+            u->audio_mgr.intf.get_volume_level(u->audio_mgr.data, audio_info.stream.volume_type, &volume_level);
+        }
+
+        pa_strbuf_printf(s, "[%s] policy[%s] ch[%d] rate[%d] volume&gain[%d,%d] level[%d]",
+                audio_info.stream.name, policy, audio_info.stream.channels, audio_info.stream.samplerate,
+                audio_info.stream.volume_type, audio_info.stream.gain_type, volume_level);
+
+        if (audio_info.device.api == AUDIO_DEVICE_API_ALSA) {
+            pa_strbuf_printf(s, " device:ALSA[%d,%d]", audio_info.device.alsa.card_idx, audio_info.device.alsa.device_idx);
+        } else if (audio_info.device.api == AUDIO_DEVICE_API_BLUEZ) {
+            pa_strbuf_printf(s, " device:BLUEZ[%s] nrec[%d]", audio_info.device.bluez.protocol, audio_info.device.bluez.nrec);
+        }
+        pa_strbuf_printf(s, " sink[%s]", (new_data->sink)? new_data->sink->name : "null");
+
+        /* Call HAL function if exists */
+        if (u->audio_mgr.intf.set_volume_level) {
+            if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.set_volume_level(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, volume_level)))) {
+                pa_log_warn("set_volume_level for new sink-input returns error:0x%x", audio_ret);
+                goto exit;
+            }
+        }
+
+        /* Get volume value by type & level */
+        if (u->audio_mgr.intf.get_volume_value && (audio_ret != AUDIO_RET_USE_HW_CONTROL)) {
+            if (AUDIO_IS_ERROR((audio_ret = u->audio_mgr.intf.get_volume_value(u->audio_mgr.data, &audio_info, audio_info.stream.volume_type, volume_level, &volume_linear)))) {
+                pa_log_warn("get_volume_value for new sink-input returns error:0x%x", audio_ret);
+                goto exit;
+            }
+        }
+
+        pa_cvolume_init(&new_data->volume);
+        pa_cvolume_set(&new_data->volume, new_data->sample_spec.channels, pa_sw_volume_from_linear(volume_linear));
+
+        new_data->volume_is_set = true;
+
+        if(u->muteall && audio_info.stream.volume_type != AUDIO_VOLUME_TYPE_FIXED) {
+            pa_sink_input_new_data_set_muted(new_data, true); // pa_simpe api use muted stream always. for play_sample_xxx apis
+        }
+        __free_audio_info(&audio_info);
+    }
+
+exit:
+    if (s) {
+        s_info = pa_strbuf_tostring_free(s);
+        pa_log_info("new %s", s_info);
+        pa_xfree(s_info);
+    }
+
+    return PA_HOOK_OK;
+}
+
+
+static pa_hook_result_t sink_input_unlink_post_hook_callback(pa_core *c, pa_sink_input *i, struct userdata *u)
+{
+    uint32_t volume_type = 0;
+    const char *si_volume_type_str;
+
+    pa_assert(c);
+    pa_assert(i);
+    pa_assert(u);
+
+#ifdef PRIMARY_VOLUME
+    if((si_volume_type_str = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
+        pa_atou(si_volume_type_str, &volume_type);
+        __set_primary_volume(u, (void*)i, volume_type, false);
+    }
+#endif
 
     return PA_HOOK_OK;
 }
 
+static pa_hook_result_t sink_input_put_callback(pa_core *core, pa_sink_input *i, struct userdata *u)
+{
+    uint32_t volume_type = 0;
+    const char *si_volume_type_str;
+
+    pa_core_assert_ref(core);
+    pa_sink_input_assert_ref(i);
+    pa_assert(u);
+
+#ifdef PRIMARY_VOLUME
+    if ((si_volume_type_str = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE)) &&
+        pa_sink_input_get_state(i) != PA_SINK_INPUT_CORKED /* if sink-input is created by pulsesink, sink-input init state is cork.*/) {
+        pa_atou(si_volume_type_str, &volume_type);
+        __set_primary_volume(u, (void*)i, volume_type, true);
+    }
+#endif
+
+    return PA_HOOK_OK;
+}
 /*  Called when new sink is added while sink-input is existing  */
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u)
 {
@@ -522,7 +3414,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct
                        policy = POLICY_AUTO;
                }
 
-               sink_to_move = policy_select_proper_sink (c, policy, u->is_mono);
+               sink_to_move = policy_select_proper_sink (u, policy, si, u->is_mono);
                if (sink_to_move) {
                        pa_log_debug("[POLICY][%s] Moving sink-input[%d] from [%s] to [%s]", __func__, si->index, si->sink->name, sink_to_move->name);
                        pa_sink_input_move_to(si, sink_to_move, false);
@@ -538,6 +3430,57 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct
 
     return PA_HOOK_OK;
 }
+static void defer_event_cb (pa_mainloop_api *m, pa_defer_event *e, void *userdata)
+{
+    struct userdata *u = userdata;
+
+    pa_assert(m);
+    pa_assert(e);
+    pa_assert(u);
+
+    m->defer_enable(u->defer_event, 0);
+
+    /* Dispatch queued events */
+
+    while (u->hal_event_queue) {
+        struct pa_hal_event *hal_event = u->hal_event_queue;
+
+        if ((hal_event->event_type == PA_HAL_EVENT_LOAD_DEVICE) || (hal_event->event_type == PA_HAL_EVENT_OPEN_DEVICE)) {
+            struct pa_hal_device_event_data *event_data = (struct pa_hal_device_event_data *)hal_event->event_data;
+
+            pa_log_info("dispatch %s event", __get_event_type_string(hal_event->event_type));
+
+            __load_n_open_device(hal_event->userdata, &event_data->device_info, &event_data->params[0], hal_event->event_type);
+
+            pa_log_debug("completed %s event", __get_event_type_string(hal_event->event_type));
+        } else if (hal_event->event_type == PA_HAL_EVENT_CLOSE_ALL_DEVICES) {
+            pa_log_info("dispatch %s event", __get_event_type_string(PA_HAL_EVENT_CLOSE_ALL_DEVICES));
+
+            __close_all_devices(hal_event->userdata);
+
+            pa_log_debug("completed %s event", __get_event_type_string(PA_HAL_EVENT_CLOSE_ALL_DEVICES));
+        } else if ((hal_event->event_type == PA_HAL_EVENT_CLOSE_DEVICE) || (hal_event->event_type == PA_HAL_EVENT_UNLOAD_DEVICE)) {
+            struct pa_hal_device_event_data *event_data = (struct pa_hal_device_event_data *)hal_event->event_data;
+
+            pa_log_info("dispatch %s event", __get_event_type_string(hal_event->event_type));
+
+            __close_n_unload_device(hal_event->userdata, &event_data->device_info, hal_event->event_type);
+
+            pa_log_debug("completed %s event", __get_event_type_string(hal_event->event_type));
+        }
+
+        if (!hal_event->next)
+            hal_event->userdata->hal_event_last = hal_event->prev;
+
+        PA_LLIST_REMOVE(struct pa_hal_event, hal_event->userdata->hal_event_queue, hal_event);
+
+        if (hal_event->cond) {
+            pa_mutex_lock(hal_event->mutex);
+            pa_cond_signal(hal_event->cond, 0);
+            pa_mutex_unlock(hal_event->mutex);
+        }
+    }
+}
 
 static void subscribe_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata)
 {
@@ -546,6 +3489,12 @@ static void subscribe_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t id
     pa_sink_input *si;
     uint32_t idx2;
     pa_sink *sink_to_move = NULL;
+    pa_sink *sink_cur = NULL;
+    pa_source *source_cur = NULL;
+    pa_source_state_t source_state;
+    int vconf_source_status = 0;
+    uint32_t si_index;
+    int audio_ret;
     pa_assert(u);
 
     pa_log_debug("[POLICY][%s] subscribe_cb() t=[0x%x], idx=[%d]", __func__, t, idx);
@@ -571,6 +3520,21 @@ static void subscribe_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t id
                        if (policy_is_filter(si))
                                continue;
 
+            if (pa_streq (def->name, "null")) {
+#ifdef TIZEN_MICRO
+                /* alarm is not comming via speaker after disconnect bluetooth. */
+                if(pa_streq(si->sink->name, "null")) {
+                    pa_log_warn("try to move sink-input from null-sink to null-sink(something wrong state). sink-input[%d] will move to proper sink", si->index);
+                } else {
+#endif
+                    pa_log_debug("Moving sink-input[%d] from [%s] to [%s]", si->index, si->sink->name, def->name);
+                    pa_sink_input_move_to(si, def, false);
+                    continue;
+#ifdef TIZEN_MICRO
+                }
+#endif
+            }
+
                        /* Get policy */
                        if (!(policy = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_POLICY))) {
                                /* No policy exists, this means auto */
@@ -578,13 +3542,58 @@ static void subscribe_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t id
                                policy = POLICY_AUTO;
                        }
 
-                       sink_to_move = policy_select_proper_sink (c, policy, u->is_mono);
+#ifdef TIZEN_MICRO
+            sink_to_move = policy_select_proper_sink (u, policy, si, u->is_mono);
+#else
+            /** If sink input is an UHQA sink then connect the sink to UHQA sink*/
+            if ((si->sample_spec.rate >= UHQA_BASE_SAMPLING_RATE)
+                 && (pa_streq(policy, POLICY_HIGH_LATENCY) || pa_streq(policy, POLICY_AUTO))) {
+                char tmp_policy[100] = {0};
+
+                sprintf(tmp_policy, "%s-uhqa", policy);
+                sink_to_move = policy_select_proper_sink (u, tmp_policy, si, u->is_mono);
+            } else {
+                sink_to_move = policy_select_proper_sink (u, policy, si, u->is_mono);
+            }
+#endif
                        if (sink_to_move) {
                                /* Move sink-input to new DEFAULT sink */
                                pa_log_debug("[POLICY][%s] Moving sink-input[%d] from [%s] to [%s]", __func__, si->index, si->sink->name, sink_to_move->name);
                                pa_sink_input_move_to(si, sink_to_move, false);
                        }
        }
+        pa_log_info("All moved to proper sink finished!!!!");
+    } else if (t == (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE)) {
+        if ((sink_cur = pa_idxset_get_by_index(c->sinks, idx))) {
+            pa_sink_state_t state = pa_sink_get_state(sink_cur);
+            pa_log_debug("sink[%s] changed to state[%d]", sink_cur->name, state);
+
+            if (pa_streq (sink_cur->name, SINK_HIGH_LATENCY) && state == PA_SINK_RUNNING) {
+                PA_IDXSET_FOREACH(si, c->sink_inputs, si_index) {
+                    if (!si->sink)
+                        continue;
+                    if (pa_streq (si->sink->name, SINK_HIGH_LATENCY)) {
+                        if (AUDIO_IS_ERROR((audio_ret = __update_volume(u, si->index, (uint32_t)-1, (uint32_t)-1)))) {
+                            pa_log_debug("__update_volume for stream[%d] returns error:0x%x", si->index, audio_ret);
+                        }
+                    }
+                }
+            }
+        }
+    } else if (t == (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE)) {
+        if ((source_cur = pa_idxset_get_by_index(c->sources, idx))) {
+            if (pa_streq (source_cur->name, SOURCE_ALSA)) {
+                source_state = pa_source_get_state(source_cur);
+                pa_log_debug("source[%s] changed to state[%d]", source_cur->name, source_state);
+                if (source_state == PA_SOURCE_RUNNING) {
+                    vconf_set_int (VCONFKEY_SOUND_CAPTURE_STATUS, 1);
+                } else {
+                    vconf_get_int (VCONFKEY_SOUND_CAPTURE_STATUS, &vconf_source_status);
+                    if (vconf_source_status)
+                        vconf_set_int (VCONFKEY_SOUND_CAPTURE_STATUS, 0);
+                }
+            }
+        }
     }
 }
 
@@ -594,6 +3603,9 @@ static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, voi
     pa_sink *sink_to_move;
     pa_sink_input      *si;
 
+    const char *si_volume_type_str;
+    uint32_t volume_type = AUDIO_VOLUME_TYPE_SYSTEM;
+
     pa_assert(c);
     pa_assert(sink);
     pa_assert(u);
@@ -616,7 +3628,7 @@ static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, voi
 
        /* BT sink is unloading, move sink-input to proper sink */
        PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
-
+        const char *policy = NULL;
                if (!si->sink)
                        continue;
 
@@ -690,7 +3702,8 @@ static pa_hook_result_t sink_unlink_post_hook_callback(pa_core *c, pa_sink *sink
 }
 
 static pa_hook_result_t sink_input_move_start_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
-    pa_core_assert_ref(core);
+       audio_return_t audio_ret = AUDIO_RET_OK;
+       pa_core_assert_ref(core);
     pa_sink_input_assert_ref(i);
 
     /* There's no point in doing anything if the core is shut down anyway */
@@ -699,13 +3712,16 @@ static pa_hook_result_t sink_input_move_start_cb(pa_core *core, pa_sink_input *i
 
     pa_log_debug ("[POLICY][%s]  sink_input_move_start_cb -------------------------------------- sink-input [%d] was sink [%s][%d] : Trying to mute!!!",
                __func__, i->index, i->sink->name, i->sink->index);
-    pa_sink_input_set_mute(i, true, false);
+    if (AUDIO_IS_ERROR((audio_ret = policy_set_mute(u, i->index, (uint32_t)-1, AUDIO_DIRECTION_OUT, 1)))) {
+        pa_log_warn("policy_set_mute(1) for stream[%d] returns error:0x%x", i->index, audio_ret);
+    }
 
     return PA_HOOK_OK;
 }
 
 static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
-    pa_core_assert_ref(core);
+    audio_return_t audio_ret = AUDIO_RET_OK;
+       pa_core_assert_ref(core);
     pa_sink_input_assert_ref(i);
 
     /* There's no point in doing anything if the core is shut down anyway */
@@ -717,10 +3733,15 @@ static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input *
                (u->bt_off_idx == -1)? "Trying to un-mute!!!!" : "skip un-mute...");
 
     /* If sink input move is caused by bt sink unlink, then skip un-mute operation */
-    if (u->bt_off_idx == -1) {
-        pa_sink_input_set_mute(i, false, false);
+    /* If sink input move is caused by bt sink unlink, then skip un-mute operation */
+    if (u->bt_off_idx == -1 && !u->muteall) {
+        if (AUDIO_IS_ERROR((audio_ret = __update_volume(u, i->index, (uint32_t)-1, (uint32_t)-1)))) {
+            pa_log_debug("__update_volume for stream[%d] returns error:0x%x", i->index, audio_ret);
+        }
+        if (AUDIO_IS_ERROR((audio_ret = policy_set_mute(u, i->index, (uint32_t)-1, AUDIO_DIRECTION_OUT, 0)))) {
+            pa_log_debug("policy_set_mute(0) for stream[%d] returns error:0x%x", i->index, audio_ret);
+        }
     }
-
     return PA_HOOK_OK;
 }
 
@@ -743,11 +3764,100 @@ static pa_source* policy_get_source_by_name (pa_core *c, const char* source_name
        return NULL;
 }
 
+static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *core, pa_sink_input *i, struct userdata *u)
+{
+    pa_sink* sink_to_move = NULL;
+    pa_sink* sink_default = NULL;
+    const char * policy = NULL;
+
+    uint32_t volume_type = 0;
+    const char *si_volume_type_str = NULL;
+    const char *si_policy_str = NULL;
+    pa_sink_input_state_t state;
+
+    pa_assert(i);
+    pa_assert(u);
+
+    if((si_volume_type_str = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
+        pa_atou(si_volume_type_str, &volume_type);
+
+        state = pa_sink_input_get_state(i);
+
+        switch(state) {
+            case PA_SINK_INPUT_CORKED:
+                si_policy_str = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_POLICY);
+
+                /* special case. media volume should be set using fake sink-input by fmradio*/
+                if(si_policy_str && pa_streq(si_policy_str, "fmradio"))
+                    break;
+
+#ifdef PRIMARY_VOLUME
+                __set_primary_volume(u, (void*)i, volume_type, false);
+#endif
+                break;
+            case PA_SINK_INPUT_DRAINED:
+            case PA_SINK_INPUT_RUNNING:
+#ifdef PRIMARY_VOLUME
+                __set_primary_volume(u, (void*)i, volume_type, true);
+#endif
+                break;
+            default:
+                break;
+        }
+    }
+
+    if(i->state == PA_SINK_INPUT_RUNNING) {
+        policy = pa_proplist_gets (i->proplist, PA_PROP_MEDIA_POLICY);
+
+        pa_log_info("---------------------------------------------");
+
+        /** If sink input is an UHQA sink sink input then connect it to UHQA sink if not connected to UHQA sink*/
+        if ( ( i->sample_spec.rate >= UHQA_BASE_SAMPLING_RATE) && (policy != NULL) &&
+             ( pa_streq (policy, POLICY_HIGH_LATENCY) || pa_streq (policy, POLICY_AUTO) )) {
+            char tmp_policy[100] = {0};
+
+            pa_log_info ("------------------------------------");
+
+            sprintf(tmp_policy, "%s-uhqa", policy);
+            sink_to_move = policy_select_proper_sink (u, tmp_policy, i, u->is_mono);
+
+            if (i->sink != sink_to_move) {
+                 if (sink_to_move) {
+                    pa_log_debug("Moving sink-input[%d] from [%s] to [%s]", i->index, i->sink->name, sink_to_move->name);
+                    pa_sink_input_move_to(i, sink_to_move, false);
+                }
+            }
+        }
+
+        /** Get the normal sink and move all sink input from normal sink to UHQA sink if normal sink and UHQA sink are different*/
+        sink_default = policy_select_proper_sink (u, policy, i, u->is_mono);
+        if ((sink_to_move != NULL) && (sink_default != NULL) && (sink_to_move != sink_default)) {
+            pa_sink_input *si = NULL;
+            uint32_t idx;
+
+            /** Check any sink input connected to normal sink then move them to UHQA sink*/
+            PA_IDXSET_FOREACH (si, sink_default->inputs, idx) {
+                pa_log_info ("------------------------------------");
+                /* Get role (if role is filter, skip it) */
+                if (policy_is_filter (si)) {
+                    continue;
+                }
+                pa_sink_input_move_to (si,  sink_to_move, false);
+            }
+        }
+    }
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_object *o, struct userdata *u) {
+    return PA_HOOK_OK;
+}
 /* Select source for given condition */
 static pa_source* policy_select_proper_source (pa_core *c, const char* policy)
-{
+{    
        pa_source* source = NULL;
        pa_source* def = NULL;
+       pa_source* source_null;
 
        if (c == NULL || policy == NULL) {
                pa_log_warn ("input param is null");
@@ -760,14 +3870,42 @@ static pa_source* policy_select_proper_source (pa_core *c, const char* policy)
                pa_log_warn ("POLICY][%s] pa_namereg_get_default_source() returns null", __func__);
                return NULL;
        }
-
-       /* Select source  to */
-       if (pa_streq(policy, POLICY_VOIP)) {
-               source = policy_get_source_by_name (c, AEC_SOURCE);
-
-       } else {
-               source = def;
-       }
+    source_null = (pa_source *)pa_namereg_get(c, "null", PA_NAMEREG_SOURCE);
+    /* if default source is set as null source, we will use it */
+    if (def == source_null)
+        return def;
+
+    /* Select source  to */
+    if (pa_streq(policy, POLICY_VOIP)) {
+        /* NOTE: Check voip source first, if not available, use AEC source  */
+        source = policy_get_source_by_name (c, SOURCE_VOIP);
+        if (source == NULL) {
+            pa_log_info ("VOIP source is not available, try to use AEC source");
+            source = policy_get_source_by_name (c, AEC_SOURCE);
+            if (source == NULL) {
+                pa_log_warn ("AEC source is not available, set to default source");
+                source = def;
+            }
+        }
+    } else if (pa_streq(policy, POLICY_MIRRORING)) {
+        source = policy_get_source_by_name (c, SOURCE_MIRRORING);
+        if (source == NULL) {
+            pa_log_info ("MIRRORING source is not available, try to use ALSA MONITOR SOURCE");
+            source = policy_get_source_by_name (c, ALSA_MONITOR_SOURCE);
+            if (source == NULL) {
+                pa_log_warn (" ALSA MONITOR SOURCE source is not available, set to default source");
+                source = def;
+            }
+        }
+    } else if (pa_streq(policy, POLICY_LOOPBACK)) {
+        source = policy_get_source_by_name (c, ALSA_MONITOR_SOURCE);
+        if (source == NULL) {
+            pa_log_warn (" ALSA MONITOR SOURCE source is not available, set to default source");
+            source = def;
+        }
+    } else {
+        source = def;
+    }
 
        pa_log_debug ("[POLICY][%s] selected source : [%s]\n", __func__, (source)? source->name : "null");
        return source;
@@ -813,11 +3951,32 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
        return PA_HOOK_OK;
 }
 
+static pa_hook_result_t source_output_put_callback(pa_core *c, pa_source_output *o, struct userdata *u)
+{
+    pa_core_assert_ref(c);
+    pa_source_output_assert_ref(o);
+    pa_assert(u);
+
+#ifdef PRIMARY_VOLUME
+    __set_primary_volume(u, (void*)o, AUDIO_PRIMARY_VOLUME_TYPE_MAX/*source-output use PRIMARY_MAX*/, true);
+#endif
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_output_unlink_post_hook_callback(pa_core *c, pa_source_output *o, struct userdata *u)
+{
+#ifdef PRIMARY_VOLUME
+    __set_primary_volume(u, (void*)o, AUDIO_PRIMARY_VOLUME_TYPE_MAX/*source-output use PRIMARY_MAX*/, false);
+#endif
+    return PA_HOOK_OK;
+}
+
 int pa__init(pa_module *m)
 {
        pa_modargs *ma = NULL;
        struct userdata *u;
-       bool on_hotplug = true, on_rescue = true;
+    pa_bool_t on_hotplug = true, on_rescue = true, wideband = false;
+    uint32_t frag_size = 0, tsched_size = 0;
 
        pa_assert(m);
 
@@ -831,34 +3990,59 @@ int pa__init(pa_module *m)
                pa_log("on_hotplug= and on_rescue= expect boolean arguments");
                goto fail;
        }
+       if (pa_modargs_get_value_boolean(ma, "use_wideband_voice", &wideband) < 0 ||
+        pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 ||
+        pa_modargs_get_value_u32(ma, "tsched_buffer_size", &tsched_size) < 0) {
+        pa_log("Failed to parse module arguments buffer info");
+        goto fail;
+    }
 
        m->userdata = u = pa_xnew0(struct userdata, 1);
        u->core = m->core;
        u->module = m;
        u->on_hotplug = on_hotplug;
+    u->wideband = wideband;
+    u->fragment_size = frag_size;
+    u->tsched_buffer_size = tsched_size;
+
+    /* A little bit later than module-stream-restore */
+    u->sink_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t)sink_state_changed_hook_cb, u);
+
+    u->sink_input_new_hook_slot =
+            pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY+10, (pa_hook_cb_t) sink_input_new_hook_callback, u);
+    u->sink_input_unlink_post_slot =
+            pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], PA_HOOK_EARLY+10, (pa_hook_cb_t) sink_input_unlink_post_hook_callback, u);
+    u->sink_input_put_slot =
+            pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_EARLY+10, (pa_hook_cb_t) sink_input_put_callback, u);
+    u->sink_input_state_changed_slot =
+             pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], PA_HOOK_EARLY+10, (pa_hook_cb_t) sink_input_state_changed_hook_cb, u);
+
+    u->source_output_new_hook_slot =
+            pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY+10, (pa_hook_cb_t) source_output_new_hook_callback, u);
+    u->source_output_unlink_post_slot =
+            pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], PA_HOOK_EARLY+10, (pa_hook_cb_t) source_output_unlink_post_hook_callback, u);
+    u->source_output_put_slot =
+            pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], PA_HOOK_EARLY+10, (pa_hook_cb_t) source_output_put_callback, u);
+
+    if (on_hotplug) {
+        /* A little bit later than module-stream-restore */
+        u->sink_put_hook_slot =
+            pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_put_hook_callback, u);
+    }
 
+    /* sink unlink comes before sink-input unlink */
+    u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) sink_unlink_hook_callback, u);
+    u->sink_unlink_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], PA_HOOK_EARLY, (pa_hook_cb_t) sink_unlink_post_hook_callback, u);
 
-       /* A little bit later than module-stream-restore */
-       u->sink_input_new_hook_slot =
-                       pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY+10, (pa_hook_cb_t) sink_input_new_hook_callback, u);
-
-       u->source_output_new_hook_slot =
-                       pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY+10, (pa_hook_cb_t) source_output_new_hook_callback, u);
-
-       if (on_hotplug) {
-               /* A little bit later than module-stream-restore */
-               u->sink_put_hook_slot =
-                       pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_put_hook_callback, u);
-       }
+    u->sink_input_move_start_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_start_cb, u);
+    u->sink_input_move_finish_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_finish_cb, u);
 
-       /* sink unlink comes before sink-input unlink */
-       u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) sink_unlink_hook_callback, u);
-       u->sink_unlink_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], PA_HOOK_EARLY, (pa_hook_cb_t) sink_unlink_post_hook_callback, u);
+    u->tid = pthread_self();
+    u->defer_event = u->core->mainloop->defer_new(u->core->mainloop, defer_event_cb, u);
 
-       u->sink_input_move_start_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_start_cb, u);
-       u->sink_input_move_finish_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_finish_cb, u);
+    u->subscription = pa_subscription_new(u->core, PA_SUBSCRIPTION_MASK_SERVER | PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, subscribe_cb, u);
 
-       u->subscription = pa_subscription_new(u->core, PA_SUBSCRIPTION_MASK_SERVER, subscribe_cb, u);
+    pa_log_debug("subscription done");
 
 
        u->bt_off_idx = -1;     /* initial bt off sink index */
@@ -870,9 +4054,59 @@ int pa__init(pa_module *m)
     u->protocol = pa_native_protocol_get(m->core);
     pa_native_protocol_install_ext(u->protocol, m, extension_cb);
 
+
+#ifdef PRIMARY_VOLUME
+    vconf_set_int (VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE, -1);
+#endif
     /* Get mono key value for init */
        vconf_get_bool(MONO_KEY, &u->is_mono);
+       /* Load library & init audio mgr */
+    u->audio_mgr.dl_handle = dlopen(LIB_TIZEN_AUDIO, RTLD_NOW);
+    if (u->audio_mgr.dl_handle) {
+        u->audio_mgr.intf.init = dlsym(u->audio_mgr.dl_handle, "audio_init");
+        u->audio_mgr.intf.deinit = dlsym(u->audio_mgr.dl_handle, "audio_deinit");
+        u->audio_mgr.intf.reset = dlsym(u->audio_mgr.dl_handle, "audio_reset");
+        u->audio_mgr.intf.set_callback = dlsym(u->audio_mgr.dl_handle, "audio_set_callback");
+        u->audio_mgr.intf.get_volume_level_max = dlsym(u->audio_mgr.dl_handle, "audio_get_volume_level_max");
+        u->audio_mgr.intf.get_volume_level = dlsym(u->audio_mgr.dl_handle, "audio_get_volume_level");
+        u->audio_mgr.intf.get_volume_value = dlsym(u->audio_mgr.dl_handle, "audio_get_volume_value");
+        u->audio_mgr.intf.set_volume_level = dlsym(u->audio_mgr.dl_handle, "audio_set_volume_level");
+        u->audio_mgr.intf.set_volume_value = dlsym(u->audio_mgr.dl_handle, "audio_set_volume_value");
+        u->audio_mgr.intf.get_gain_value = dlsym(u->audio_mgr.dl_handle, "audio_get_gain_value");
+        u->audio_mgr.intf.get_mute = dlsym(u->audio_mgr.dl_handle, "audio_get_mute");
+        u->audio_mgr.intf.set_mute = dlsym(u->audio_mgr.dl_handle, "audio_set_mute");
+        u->audio_mgr.intf.alsa_pcm_open = dlsym(u->audio_mgr.dl_handle, "audio_alsa_pcm_open");
+        u->audio_mgr.intf.alsa_pcm_close = dlsym(u->audio_mgr.dl_handle, "audio_alsa_pcm_close");
+        u->audio_mgr.intf.set_session = dlsym(u->audio_mgr.dl_handle, "audio_set_session");
+        u->audio_mgr.intf.set_route = dlsym(u->audio_mgr.dl_handle, "audio_set_route");
+        u->audio_mgr.intf.set_mixer_value_string = dlsym(u->audio_mgr.dl_handle, "audio_set_mixer_value_string");
+
+        if (u->audio_mgr.intf.init) {
+            if (u->audio_mgr.intf.init(&u->audio_mgr.data, (void *)u) != AUDIO_RET_OK) {
+                pa_log_error("audio_mgr init failed");
+            }
+        }
+
+        pa_shared_set(u->core, "tizen-audio-data", u->audio_mgr.data);
+        pa_shared_set(u->core, "tizen-audio-interface", &u->audio_mgr.intf);
 
+        if (u->audio_mgr.intf.set_callback) {
+            audio_cb_interface_t cb_interface;
+
+            cb_interface.load_device = __load_device_callback;
+            cb_interface.open_device = __open_device_callback;
+            cb_interface.close_all_devices = __close_all_devices_callback;
+            cb_interface.close_device = __close_device_callback;
+            cb_interface.unload_device = __unload_device_callback;
+            u->audio_mgr.intf.set_callback(u->audio_mgr.data, &cb_interface);
+        }
+        
+    } else {
+        pa_log_error("open audio_mgr failed :%s", dlerror());
+    }
+#if 0
+    __load_dump_config(u);
+ #endif
        pa_log_info("policy module is loaded\n");
 
        if (ma)
@@ -906,6 +4140,8 @@ void pa__done(pa_module *m)
         pa_hook_slot_free(u->sink_unlink_slot);
     if (u->sink_unlink_post_slot)
         pa_hook_slot_free(u->sink_unlink_post_slot);
+    if(u->sink_input_state_changed_slot)
+         pa_hook_slot_free(u->sink_input_state_changed_slot);
     if (u->sink_input_move_start_slot)
         pa_hook_slot_free(u->sink_input_move_start_slot);
     if (u->sink_input_move_finish_slot)
@@ -918,6 +4154,16 @@ void pa__done(pa_module *m)
     }
     if (u->source_output_new_hook_slot)
         pa_hook_slot_free(u->source_output_new_hook_slot);
+               
+       /* Deinit audio mgr & unload library */
+    if (u->audio_mgr.intf.deinit) {
+        if (u->audio_mgr.intf.deinit(&u->audio_mgr.data) != AUDIO_RET_OK) {
+            pa_log_error("audio_mgr deinit failed");
+        }
+    }
+    if (u->audio_mgr.dl_handle) {
+        dlclose(u->audio_mgr.dl_handle);
+    }
 
     pa_xfree(u);
 
diff --git a/src/modules/tizen-audio.h b/src/modules/tizen-audio.h
new file mode 100755 (executable)
index 0000000..33b6801
--- /dev/null
@@ -0,0 +1,292 @@
+#ifndef foopulsetizenaudiofoo
+#define foopulsetizenaudiofoo
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2013 Hyunseok Lee <hs7388.lee@samsung.com>
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+/* FIXME : This file should be separated from PA in future */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#define AUDIO_REVISION                  1
+
+/* Error code */
+
+#define AUDIO_IS_ERROR(ret)             (ret < 0)
+
+typedef enum audio_return {
+    AUDIO_RET_OK                        = 0,
+    AUDIO_RET_USE_HW_CONTROL            = (int32_t)0x40001000,
+    AUDIO_ERR_UNDEFINED                 = (int32_t)0x80001000,
+    AUDIO_ERR_RESOURCE                  = (int32_t)0x80001001,
+    AUDIO_ERR_PARAMETER                 = (int32_t)0x80001002,
+    AUDIO_ERR_IOCTL                     = (int32_t)0x80001003,
+    AUDIO_ERR_NOT_IMPLEMENTED           = (int32_t)0x80001004,
+} audio_return_t ;
+
+
+/* Session */
+typedef enum audio_session {
+    AUDIO_SESSION_MEDIA,
+    AUDIO_SESSION_VOICECALL,
+    AUDIO_SESSION_VIDEOCALL,
+    AUDIO_SESSION_VOIP,
+    AUDIO_SESSION_FMRADIO,
+    AUDIO_SESSION_CAMCORDER,
+    AUDIO_SESSION_NOTIFICATION,
+    AUDIO_SESSION_ALARM,
+    AUDIO_SESSION_EMERGENCY,
+    AUDIO_SESSION_VOICE_RECOGNITION,
+    AUDIO_SESSION_MAX
+} audio_session_t;
+
+/* Sub session */
+typedef enum audio_subsession {
+    AUDIO_SUBSESSION_NONE,
+    AUDIO_SUBSESSION_VOICE,
+    AUDIO_SUBSESSION_RINGTONE,
+    AUDIO_SUBSESSION_MEDIA,
+    AUDIO_SUBSESSION_INIT,
+    AUDIO_SUBSESSION_VR_NORMAL,
+    AUDIO_SUBSESSION_VR_DRIVE,
+    AUDIO_SUBSESSION_STEREO_REC,
+    AUDIO_SUBSESSION_MONO_REC,
+    AUDIO_SUBSESSION_MAX
+} audio_subsession_t;
+
+/* Session command */
+typedef enum audio_session_command {
+    AUDIO_SESSION_CMD_START,
+    AUDIO_SESSION_CMD_SUBSESSION,
+    AUDIO_SESSION_CMD_END,
+} audio_session_command_t;
+
+
+/* Direction */
+typedef enum audio_direction {
+    AUDIO_DIRECTION_NONE,
+    AUDIO_DIRECTION_IN,                 /**< Capture */
+    AUDIO_DIRECTION_OUT,                /**< Playback */
+} audio_direction_t;
+
+
+/* Device */
+
+typedef enum audio_device_in {
+    AUDIO_DEVICE_IN_NONE,
+    AUDIO_DEVICE_IN_MIC,                /**< Device builtin mic. */
+    AUDIO_DEVICE_IN_WIRED_ACCESSORY,    /**< Wired input devices */
+    AUDIO_DEVICE_IN_BT_SCO,             /**< Bluetooth SCO device */
+    AUDIO_DEVICE_IN_MAX,
+} audio_device_in_t;
+
+typedef enum audio_device_out {
+    AUDIO_DEVICE_OUT_NONE,
+    AUDIO_DEVICE_OUT_SPEAKER,           /**< Device builtin speaker */
+    AUDIO_DEVICE_OUT_RECEIVER,          /**< Device builtin receiver */
+    AUDIO_DEVICE_OUT_WIRED_ACCESSORY,   /**< Wired output devices such as headphone, headset, and so on. */
+    AUDIO_DEVICE_OUT_BT_SCO,            /**< Bluetooth SCO device */
+    AUDIO_DEVICE_OUT_BT_A2DP,           /**< Bluetooth A2DP device */
+    AUDIO_DEVICE_OUT_DOCK,              /**< DOCK device */
+    AUDIO_DEVICE_OUT_HDMI,              /**< HDMI device */
+    AUDIO_DEVICE_OUT_MIRRORING,         /**< MIRRORING device */
+    AUDIO_DEVICE_OUT_USB_AUDIO,         /**< USB Audio device */
+    AUDIO_DEVICE_OUT_MULTIMEDIA_DOCK,   /**< Multimedia DOCK device */
+    AUDIO_DEVICE_OUT_MAX,
+} audio_device_out_t;
+
+typedef enum audio_route_flag {
+    AUDIO_ROUTE_FLAG_NONE               = 0,
+    AUDIO_ROUTE_FLAG_MUTE_POLICY        = 0x00000001,
+    AUDIO_ROUTE_FLAG_DUAL_OUT           = 0x00000002,
+    AUDIO_ROUTE_FLAG_NOISE_REDUCTION    = 0x00000010,
+    AUDIO_ROUTE_FLAG_EXTRA_VOL          = 0x00000020,
+    AUDIO_ROUTE_FLAG_NETWORK_WB         = 0x00000040,
+    AUDIO_ROUTE_FLAG_BT_WB              = 0x00000100,
+    AUDIO_ROUTE_FLAG_BT_NREC            = 0x00000200,
+    AUDIO_ROUTE_FLAG_VOICE_COMMAND      = 0x00040000,
+} audio_route_flag_t;
+
+typedef enum audio_device_api {
+    AUDIO_DEVICE_API_UNKNOWN,
+    AUDIO_DEVICE_API_ALSA,
+    AUDIO_DEVICE_API_BLUEZ,
+} audio_device_api_t;
+
+typedef enum audio_device_param {
+    AUDIO_DEVICE_PARAM_NONE,
+    AUDIO_DEVICE_PARAM_CHANNELS,
+    AUDIO_DEVICE_PARAM_SAMPLERATE,
+    AUDIO_DEVICE_PARAM_FRAGMENT_SIZE,
+    AUDIO_DEVICE_PARAM_FRAGMENT_NB,
+    AUDIO_DEVICE_PARAM_START_THRESHOLD,
+    AUDIO_DEVICE_PARAM_USE_MMAP,
+    AUDIO_DEVICE_PARAM_USE_TSCHED,
+    AUDIO_DEVICE_PARAM_TSCHED_BUF_SIZE,
+    AUDIO_DEVICE_PARAM_SUSPEND_TIMEOUT,
+    AUDIO_DEVICE_PARAM_ALTERNATE_RATE,
+    AUDIO_DEVICE_PARAM_MAX,
+} audio_device_param_t;
+
+typedef struct audio_device_param_info {
+    audio_device_param_t param;
+    union {
+        int64_t s64_v;
+        uint64_t u64_v;
+        int32_t s32_v;
+        uint32_t u32_v;
+    };
+} audio_device_param_info_t;
+
+typedef struct audio_device_alsa_info {
+    char *card_name;
+    uint32_t card_idx;
+    uint32_t device_idx;
+} audio_device_alsa_info_t;
+
+typedef struct audio_device_bluz_info {
+    char *protocol;
+    uint32_t nrec;
+} audio_device_bluez_info_t;
+
+typedef struct audio_device_info {
+    audio_device_api_t api;
+    audio_direction_t direction;
+    char *name;
+    uint8_t is_default_device;
+    union {
+        audio_device_alsa_info_t alsa;
+        audio_device_bluez_info_t bluez;
+    };
+} audio_device_info_t;
+
+
+/* Stream */
+
+typedef enum audio_volume {
+    AUDIO_VOLUME_TYPE_SYSTEM,           /**< System volume type */
+    AUDIO_VOLUME_TYPE_NOTIFICATION,     /**< Notification volume type */
+    AUDIO_VOLUME_TYPE_ALARM,            /**< Alarm volume type */
+    AUDIO_VOLUME_TYPE_RINGTONE,         /**< Ringtone volume type */
+    AUDIO_VOLUME_TYPE_MEDIA,            /**< Media volume type */
+    AUDIO_VOLUME_TYPE_CALL,             /**< Call volume type */
+    AUDIO_VOLUME_TYPE_VOIP,             /**< VOIP volume type */
+    AUDIO_VOLUME_TYPE_VOICE,            /**< Voice volume type */
+    AUDIO_VOLUME_TYPE_FIXED,            /**< Volume type for fixed acoustic level */
+    AUDIO_VOLUME_TYPE_MAX,              /**< Volume type count */
+} audio_volume_t;
+
+#ifdef PRIMARY_VOLUME
+typedef enum audio_primary_volume {
+    AUDIO_PRIMARY_VOLUME_TYPE_CALL,             /**< Call volume type */
+    AUDIO_PRIMARY_VOLUME_TYPE_VOIP,             /**< VOIP volume type */
+    AUDIO_PRIMARY_VOLUME_TYPE_RINGTONE,         /**< Ringtone volume type */
+    AUDIO_PRIMARY_VOLUME_TYPE_VOICE,            /**< Voice volume type */
+    AUDIO_PRIMARY_VOLUME_TYPE_MEDIA,            /**< Media volume type */
+    AUDIO_PRIMARY_VOLUME_TYPE_ALARM,            /**< Alarm volume type */
+    AUDIO_PRIMARY_VOLUME_TYPE_NOTIFICATION,     /**< Notification volume type */
+    AUDIO_PRIMARY_VOLUME_TYPE_SYSTEM,           /**< System volume type */
+    AUDIO_PRIMARY_VOLUME_TYPE_FIXED,            /**< Volume type for fixed acoustic level */
+    AUDIO_PRIMARY_VOLUME_TYPE_MAX,              /**< Volume type count */
+} audio_primary_volume_t;
+#endif
+
+typedef enum audio_gain {
+    AUDIO_GAIN_TYPE_DEFAULT,
+    AUDIO_GAIN_TYPE_DIALER,
+    AUDIO_GAIN_TYPE_TOUCH,
+    AUDIO_GAIN_TYPE_AF,
+    AUDIO_GAIN_TYPE_SHUTTER1,
+    AUDIO_GAIN_TYPE_SHUTTER2,
+    AUDIO_GAIN_TYPE_CAMCODING,
+    AUDIO_GAIN_TYPE_MIDI,
+    AUDIO_GAIN_TYPE_BOOTING,
+    AUDIO_GAIN_TYPE_VIDEO,
+    AUDIO_GAIN_TYPE_TTS,
+    AUDIO_GAIN_TYPE_MAX,
+} audio_gain_t;
+
+typedef struct audio_stream_info {
+    char *name;
+    uint32_t samplerate;
+    uint8_t channels;
+    uint32_t volume_type;
+    uint32_t gain_type;
+} audio_stream_info_t ;
+
+
+/* Overall */
+
+typedef struct audio_info {
+    audio_device_info_t device;
+    audio_stream_info_t stream;
+} audio_info_t;
+
+typedef struct audio_cb_interface {
+    audio_return_t (*load_device)(void *platform_data, audio_device_info_t *device_info, audio_device_param_info_t *params);
+    audio_return_t (*open_device)(void *platform_data, audio_device_info_t *device_info, audio_device_param_info_t *params);
+    audio_return_t (*close_all_devices)(void *platform_data);
+    audio_return_t (*close_device)(void *platform_data, audio_device_info_t *device_info);
+    audio_return_t (*unload_device)(void *platform_data, audio_device_info_t *device_info);
+} audio_cb_interface_t;
+
+typedef struct audio_interface {
+    audio_return_t (*init)(void **userdata, void *platform_data);
+    audio_return_t (*deinit)(void **userdata);
+    audio_return_t (*reset)(void **userdata);
+    audio_return_t (*set_callback)(void *userdata, audio_cb_interface_t *cb_interface);
+    audio_return_t (*get_volume_level_max)(void *userdata, uint32_t volume_type, uint32_t *level);
+    audio_return_t (*get_volume_level)(void *userdata, uint32_t volume_type, uint32_t *level);
+    audio_return_t (*get_volume_value)(void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level, double *value);
+    audio_return_t (*set_volume_level)(void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level);
+    audio_return_t (*set_volume_value)(void *userdata, audio_info_t *info, uint32_t volume_type, double* value);
+    audio_return_t (*get_gain_value)(void *userdata, audio_info_t *info, uint32_t volume_type, double *value);
+    audio_return_t (*get_mute)(void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t *mute);
+    audio_return_t (*set_mute)(void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t mute);
+    audio_return_t (*set_session)(void *userdata, uint32_t session, uint32_t subsession, uint32_t cmd);
+    audio_return_t (*set_route)(void *userdata, uint32_t session, uint32_t subsession, uint32_t device_in, uint32_t device_out, uint32_t route_flag);
+    audio_return_t (*alsa_pcm_open)(void *userdata, void **pcm_handle, char *device_name, uint32_t direction, int mode);
+    audio_return_t (*alsa_pcm_close)(void *userdata, void *pcm_handle);
+    audio_return_t (*set_mixer_value_string)(void *userdata, const char* ctl, const char* value);
+
+} audio_interface_t;
+
+int audio_get_revision (void);
+audio_return_t audio_init (void **userdata, void *platform_data);
+audio_return_t audio_deinit (void **userdata);
+audio_return_t audio_reset (void **userdata);
+audio_return_t audio_set_callback (void *userdata, audio_cb_interface_t *cb_interface);
+audio_return_t audio_get_volume_level_max (void *userdata, uint32_t volume_type, uint32_t *level);
+audio_return_t audio_get_volume_level (void *userdata, uint32_t volume_type, uint32_t *level);
+audio_return_t audio_get_volume_value (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level, double *value);
+audio_return_t audio_set_volume_level (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level);
+audio_return_t audio_set_volume_value (void *userdata, audio_info_t *info, uint32_t volume_type, double* value);
+audio_return_t audio_get_gain_value (void *userdata, audio_info_t *info, uint32_t volume_type, double *value);
+audio_return_t audio_get_mute (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t *mute);
+audio_return_t audio_set_mute (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t mute);
+audio_return_t audio_set_session (void *userdata, uint32_t session, uint32_t subsession, uint32_t cmd);
+audio_return_t audio_alsa_pcm_open (void *userdata, void **pcm_handle, char *device_name, uint32_t direction, int mode);
+audio_return_t audio_alsa_pcm_close (void *userdata, void *pcm_handle);
+audio_return_t audio_set_route (void *userdata, uint32_t session, uint32_t subsession, uint32_t device_in, uint32_t device_out, uint32_t route_flag);
+
+#endif
index 341abaa..65a93a5 100644 (file)
 
 PA_C_DECL_BEGIN
 
+#ifdef __TIZEN__
+#define PA_PROP_MEDIA_TIZEN_VOLUME_TYPE        "media.tizen_volume_type"
+#define PA_PROP_MEDIA_TIZEN_GAIN_TYPE          "media.tizen_gain_type"
+#define PA_PROP_MEDIA_TIZEN_FADE_STATUS        "media.tizen_fade_status"
+#define PA_PROP_MEDIA_TIZEN_FADE_RETURN_VOLUME "media.tizen_fade_return_volume"
+/** For streams: the policy to ignore the preset sink rather use a sink picked by module-policy. One of the strings "yes", "no" */
+#define PA_PROP_MEDIA_POLICY_IGNORE_PRESET_SINK  "media.policy.ignore_preset_sink"
+#endif
+
 /** For streams: localized media name, formatted as UTF-8. E.g. "Guns'N'Roses: Civil War".*/
 #define PA_PROP_MEDIA_NAME                     "media.name"
 
index 4d5e80f..3fd3778 100644 (file)
 #define PA_PAGE_SIZE ((size_t) 4096)
 #endif
 
+#ifdef __TIZEN__
+typedef int  pa_bool_t;
+#else
+typedef bool pa_bool_t;
+#endif
+
+
 /* Rounds down */
 static inline void* PA_ALIGN_PTR(const void *p) {
     return (void*) (((size_t) p) & ~(sizeof(void*) - 1));