diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index 6b9be62..2d299e3 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -744,6 +744,7 @@ void ucm_add_ports(pa_hashmap **p, pa_proplist *proplist,
     int *dev_indices = pa_xnew(int, context->ucm_devices_num);
     int i;
     char *merged_roles;
+    const char *role_name = is_sink ? PA_PROP_UCM_PLAYBACK_ROLES : PA_PROP_UCM_CAPTURE_ROLES;
 
     pa_assert(p);
     pa_assert(!*p);
@@ -759,7 +760,7 @@ void ucm_add_ports(pa_hashmap **p, pa_proplist *proplist,
     for (i=0; i<context->ucm_devices_num; i++)
     {
         const char *roles = pa_proplist_gets(
-                context->ucm_devices[i]->proplist, PA_PROP_DEVICE_INTENDED_ROLES);
+                context->ucm_devices[i]->proplist, role_name);
         char *tmp;
         tmp = merge_roles(merged_roles, roles);
         pa_xfree(merged_roles);
@@ -894,6 +895,12 @@ static void alsa_mapping_add_ucm_device(pa_alsa_mapping *m, pa_alsa_ucm_device *
 
     /* walk around null case */
     m->description = m->description ? m->description : pa_xstrdup("");
+
+    /* save mapping to ucm device */
+    if (m->direction == PA_ALSA_DIRECTION_OUTPUT)
+        device->playback_mapping = m;
+    else
+        device->capture_mapping = m;
 }
 
 static int ucm_create_mapping_direction(struct pa_alsa_ucm_config *ucm,
@@ -1094,3 +1101,91 @@ void ucm_free(struct pa_alsa_ucm_config *ucm) {
         ucm->ucm_mgr = NULL;
     }
 }
+
+static pa_bool_t stream_routed_to_mod_intent (struct pa_alsa_ucm_verb *verb,
+        struct pa_alsa_ucm_modifier *mod, const char *mapping_name) {
+    int i;
+    const char *dev_name;
+    struct pa_alsa_ucm_device *dev;
+    pa_alsa_mapping *mapping;
+
+    /* check if mapping_name is same as one of the modifier's supported device */
+    for (i=0; i<mod->n_suppdev; i++) {
+        dev_name = mod->supported_devices[i];
+        /* first find the supported device */
+        PA_LLIST_FOREACH(dev, verb->devices) {
+            const char *name = pa_proplist_gets(dev->proplist, PA_PROP_UCM_NAME);
+            if (pa_streq(name, dev_name)) {
+                /* then match the mapping name */
+                mapping = mod->action_direct == PA_ALSA_UCM_DIRECT_SINK ? dev->playback_mapping : dev->capture_mapping;
+                if (mapping && pa_streq(mapping->name, mapping_name))
+                    return TRUE;
+                break;
+            }
+        }
+    }
+
+    return FALSE;
+}
+
+/* enable the modifier when both of the conditions are met
+ * 1. the first stream with matched role starts
+ * 2. the stream is routed to the device of the modifier specifies.
+ */
+void ucm_roled_stream_begin(pa_alsa_ucm_config *ucm,
+        const char *role, const char *mapping_name, int is_sink) {
+    struct pa_alsa_ucm_modifier *mod;
+
+    if (!ucm->active_verb)
+        return;
+
+    PA_LLIST_FOREACH(mod, ucm->active_verb->modifiers) {
+        if (((mod->action_direct == PA_ALSA_UCM_DIRECT_SINK && is_sink) ||
+            (mod->action_direct == PA_ALSA_UCM_DIRECT_SOURCE && !is_sink)) &&
+            (!strcasecmp(mod->media_role, role))) {
+            if (stream_routed_to_mod_intent(ucm->active_verb, mod, mapping_name)) {
+                if (mod->enabled_counter == 0) {
+                    const char *mod_name = pa_proplist_gets(mod->proplist, PA_PROP_UCM_NAME);
+                    pa_log_info("Enable ucm modifiers %s", mod_name);
+                    if (snd_use_case_set(ucm->ucm_mgr, "_enamod", mod_name) < 0) {
+                        pa_log("failed to enable ucm modifier %s", mod_name);
+                    }
+                }
+                mod->enabled_counter++;
+                //TODO: set port of the sink/source to modifier's intent device? */
+            }
+            break;
+        }
+    }
+}
+
+/* disable the modifier when both of the conditions are met
+ * 1. the last stream with matched role ends
+ * 2. the stream is routed to the device of the modifier specifies.
+ */
+void ucm_roled_stream_end(pa_alsa_ucm_config *ucm,
+        const char *role, const char *mapping_name, int is_sink) {
+    struct pa_alsa_ucm_modifier *mod;
+
+    if (!ucm->active_verb)
+        return;
+
+    PA_LLIST_FOREACH(mod, ucm->active_verb->modifiers) {
+        if (((mod->action_direct == PA_ALSA_UCM_DIRECT_SINK && is_sink) ||
+            (mod->action_direct == PA_ALSA_UCM_DIRECT_SOURCE && !is_sink)) &&
+            (!strcasecmp(mod->media_role, role))) {
+            if (stream_routed_to_mod_intent(ucm->active_verb, mod, mapping_name)) {
+                mod->enabled_counter--;
+                if (mod->enabled_counter == 0) {
+                    const char *mod_name = pa_proplist_gets(mod->proplist, PA_PROP_UCM_NAME);
+                    pa_log_info("Disable ucm modifiers %s", mod_name);
+                    if (snd_use_case_set(ucm->ucm_mgr, "_dismod", mod_name) < 0) {
+                        pa_log("failed to disable ucm modifier %s", mod_name);
+                    }
+                }
+                //TODO: set port of the sink/source to modifier's intent device? */
+            }
+            break;
+        }
+    }
+}
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
index c0ebfe9..680be5a 100644
--- a/src/modules/alsa/alsa-ucm.h
+++ b/src/modules/alsa/alsa-ucm.h
@@ -27,6 +27,8 @@
 #include <asoundlib.h>
 #include <use-case.h>
 
+typedef struct pa_alsa_mapping pa_alsa_mapping;
+
 typedef struct pa_alsa_ucm_verb pa_alsa_ucm_verb;
 typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier;
 typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
@@ -43,6 +45,9 @@ void ucm_add_ports_combination(pa_hashmap *hash, pa_alsa_ucm_mapping_context *co
         int dev_num, int map_index, pa_hashmap *ports, pa_card_profile *cp, pa_core *core);
 int  ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *port, int is_sink);
 
+void ucm_roled_stream_begin(pa_alsa_ucm_config *ucm, const char *role, const char *mapping_name, int is_sink);
+void ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, const char *mapping_name, int is_sink);
+
 /* UCM modifier action direction */
 enum {
     PA_ALSA_UCM_DIRECT_NONE = 0,
@@ -59,6 +64,8 @@ struct pa_alsa_ucm_device {
     unsigned capture_priority;
     unsigned playback_channels;
     unsigned capture_channels;
+    pa_alsa_mapping *playback_mapping;
+    pa_alsa_mapping *capture_mapping;
     int n_confdev;
     int n_suppdev;
     char **conflicting_devices;
@@ -74,6 +81,9 @@ struct pa_alsa_ucm_modifier {
     const char **supported_devices;
     int action_direct;
     char *media_role;
+
+    /* runtime variable */
+    int enabled_counter;
 };
 
 struct pa_alsa_ucm_verb {
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index 7433ecf..d7f1043 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -124,6 +124,18 @@ struct userdata {
     /* ucm stuffs */
     pa_bool_t use_ucm;
     pa_alsa_ucm_config ucm;
+
+    /* hooks for modifier action */
+    pa_hook_slot
+        *sink_input_put_hook_slot,
+        *source_output_put_hook_slot,
+        *sink_input_unlink_hook_slot,
+        *source_output_unlink_hook_slot,
+
+        *sink_input_move_start_hook_slot,
+        *source_output_move_start_hook_slot,
+        *sink_input_move_finish_hook_slot,
+        *source_output_move_finish_hook_slot;
 };
 
 struct profile_data {
@@ -512,6 +524,103 @@ name_fail:
     return err;
 }
 
+static pa_hook_result_t sink_input_put_hook_callback(
+        pa_core *c, pa_sink_input *sink_input, struct userdata *u) {
+    const char *role;
+    const char *mapping_name;
+    pa_sink *sink = sink_input->sink;
+
+    pa_assert(sink);
+
+    role = pa_proplist_gets(sink_input->proplist, PA_PROP_MEDIA_ROLE);
+    mapping_name = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_PROFILE_NAME);
+
+    /* new sink input linked to sink of this card */
+    if (role && sink->card == u->card) {
+        ucm_roled_stream_begin(&u->ucm, role, mapping_name, 1);
+    }
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_output_put_hook_callback(
+        pa_core *c, pa_source_output *source_output, struct userdata *u) {
+    const char *role;
+    const char *mapping_name;
+    pa_source *source = source_output->source;
+
+    pa_assert(source);
+
+    role = pa_proplist_gets(source_output->proplist, PA_PROP_MEDIA_ROLE);
+    mapping_name = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_PROFILE_NAME);
+
+    /* new source output linked to source of this card */
+    if (role && source->card == u->card) {
+        ucm_roled_stream_begin(&u->ucm, role, mapping_name, 0);
+    }
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_input_unlink_hook_callback(
+        pa_core *c, pa_sink_input *sink_input, struct userdata *u) {
+    const char *role;
+    const char *mapping_name;
+    pa_sink *sink = sink_input->sink;
+
+    pa_assert(sink);
+
+    role = pa_proplist_gets(sink_input->proplist, PA_PROP_MEDIA_ROLE);
+    mapping_name = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_PROFILE_NAME);
+
+    /* new sink input unlinked from sink of this card */
+    if (role && sink->card == u->card) {
+        ucm_roled_stream_end(&u->ucm, role, mapping_name, 1);
+    }
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_output_unlink_hook_callback(
+        pa_core *c, pa_source_output *source_output, struct userdata *u) {
+    const char *role;
+    const char *mapping_name;
+    pa_source *source = source_output->source;
+
+    pa_assert(source);
+
+    role = pa_proplist_gets(source_output->proplist, PA_PROP_MEDIA_ROLE);
+    mapping_name = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_PROFILE_NAME);
+
+    /* new source output unlinked from source of this card */
+    if (role && source->card == u->card) {
+        ucm_roled_stream_end(&u->ucm, role, mapping_name, 0);
+    }
+
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_input_move_start_hook_callback(
+        pa_core *c, pa_sink_input *sink_input, struct userdata *u) {
+    /* same as sink input unlink */
+    return sink_input_unlink_hook_callback (c, sink_input, u);
+}
+
+static pa_hook_result_t source_output_move_start_hook_callback(
+        pa_core *c, pa_source_output *source_output, struct userdata *u) {
+    /* same as source output unlink */
+    return source_output_unlink_hook_callback (c, source_output, u);
+}
+
+static pa_hook_result_t sink_input_move_finish_hook_callback(
+        pa_core *c, pa_sink_input *sink_input, struct userdata *u) {
+    /* same as sink input put */
+    return sink_input_put_hook_callback (c, sink_input, u);
+}
+
+static pa_hook_result_t source_output_move_finish_hook_callback(
+        pa_core *c, pa_source_output *source_output, struct userdata *u) {
+    /* same as source output put */
+    return source_output_put_hook_callback (c, source_output, u);
+}
+
 int pa__init(pa_module *m) {
     pa_card_new_data data;
     pa_modargs *ma;
@@ -563,6 +672,38 @@ int pa__init(pa_module *m) {
     pa_modargs_get_value_boolean(ma, "use_ucm", &u->use_ucm);
     if (u->use_ucm && !card_query_ucm_profiles(u, u->alsa_card_index)) {
         pa_log_info("Found UCM profiles");
+
+        /* hook start of sink input/source output to enable modifiers */
+        /* A little bit later than module-role-cork */
+        u->sink_input_put_hook_slot = pa_hook_connect(
+                &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_LATE+10,
+                (pa_hook_cb_t) sink_input_put_hook_callback, u);
+        u->source_output_put_hook_slot = pa_hook_connect(
+                &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], PA_HOOK_LATE+10,
+                (pa_hook_cb_t) source_output_put_hook_callback, u);
+
+        /* hook end of sink input/source output to disable modifiers */
+        /* A little bit later than module-role-cork */
+        u->sink_input_unlink_hook_slot = pa_hook_connect(
+                &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK],
+                PA_HOOK_LATE+10, (pa_hook_cb_t) sink_input_unlink_hook_callback, u);
+        u->source_output_unlink_hook_slot = pa_hook_connect(
+                &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK],
+                PA_HOOK_LATE+10, (pa_hook_cb_t) source_output_unlink_hook_callback, u);
+
+        /* hook move start of sink input/source output to disable modifiers */
+        /* A little bit later than module-role-cork */
+        u->sink_input_move_start_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START],
+                PA_HOOK_LATE+10, (pa_hook_cb_t) sink_input_move_start_hook_callback, u);
+        u->source_output_move_start_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START],
+                PA_HOOK_LATE+10, (pa_hook_cb_t) source_output_move_start_hook_callback, u);
+
+        /* hook move finish of sink input/source output to enable modifiers */
+        /* A little bit later than module-role-cork */
+        u->sink_input_move_finish_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH],
+                PA_HOOK_LATE+10, (pa_hook_cb_t) sink_input_move_finish_hook_callback, u);
+        u->source_output_move_finish_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH],
+                PA_HOOK_LATE+10, (pa_hook_cb_t) source_output_move_finish_hook_callback, u);
     }
     else {
         u->use_ucm = FALSE;
@@ -695,6 +836,30 @@ void pa__done(pa_module*m) {
     if (!(u = m->userdata))
         goto finish;
 
+    if (u->sink_input_put_hook_slot)
+        pa_hook_slot_free(u->sink_input_put_hook_slot);
+
+    if (u->sink_input_unlink_hook_slot)
+        pa_hook_slot_free(u->sink_input_unlink_hook_slot);
+
+    if (u->source_output_put_hook_slot)
+        pa_hook_slot_free(u->source_output_put_hook_slot);
+
+    if (u->source_output_unlink_hook_slot)
+        pa_hook_slot_free(u->source_output_unlink_hook_slot);
+
+    if (u->sink_input_move_start_hook_slot)
+        pa_hook_slot_free(u->sink_input_move_start_hook_slot);
+
+    if (u->source_output_move_start_hook_slot)
+        pa_hook_slot_free(u->source_output_move_start_hook_slot);
+
+    if (u->sink_input_move_finish_hook_slot)
+        pa_hook_slot_free(u->sink_input_move_finish_hook_slot);
+
+    if (u->source_output_move_finish_hook_slot)
+        pa_hook_slot_free(u->source_output_move_finish_hook_slot);
+
     if (u->mixer_fdl)
         pa_alsa_fdlist_free(u->mixer_fdl);
     if (u->mixer_handle)
