Revise unnecessary logs, remove build warnings
[platform/core/multimedia/libmm-sound.git] / focus_server / mm_sound_mgr_focus.c
index 650e7c3..d614b78 100644 (file)
@@ -60,7 +60,7 @@ typedef struct {
 #define CLEAR_DEAD_NODE_LIST(x)  do { \
        debug_warning("list = %p, node = %p, pid=[%d]", x, node, (node)? node->pid : -1); \
        if (x && node && (mm_sound_util_is_process_alive(node->pid) == FALSE)) { \
-               debug_warning("PID:%d does not exist now! remove from device cb list\n", node->pid); \
+               debug_warning("PID:%d does not exist now! remove from device cb list", node->pid); \
                __clear_focus_pipe(node); \
                x = g_list_remove (x, node); \
                g_free (node); \
@@ -74,8 +74,14 @@ typedef struct {
        x_node->taken_##x_postfix[i].by_session = x_by_session; \
 } while (0)
 
-#define CHECK_MY_NODE(x_node, x_param) \
-       (x_node && !x_node->is_for_watch && (x_node->pid == x_param->pid) && (x_node->handle_id == x_param->handle_id) && (x_node->is_for_session == x_param->is_for_session))
+#define CONTINUE_IF_LIST_DATA_IS_NULL(x_node, x_list) \
+       if (!((x_node) = (focus_node_t *)(x_list)->data)) \
+               continue; \
+
+#define CONTINUE_IF_NOT_MY_FOCUS_NODE(x_node, x_param) \
+       if ((x_node)->is_for_watch || ((x_node)->pid != (x_param)->pid) || ((x_node)->handle_id != (x_param)->handle_id) || \
+           ((x_node)->is_for_session != (x_param)->is_for_session)) \
+               continue; \
 
 static char* __get_focus_pipe_path(int instance_id, int handle, const char* postfix, bool is_watch)
 {
@@ -144,7 +150,7 @@ static int _mm_sound_mgr_focus_get_priority_from_stream_type(int *priority, cons
 
        if (priority == NULL || stream_type == NULL) {
                ret = MM_ERROR_INVALID_ARGUMENT;
-               debug_error("invalid argument, priority[0x%x], stream_type[%s], ret[0x%x]\n", priority, stream_type, ret);
+               debug_error("invalid argument, priority[0x%x], stream_type[%s], ret[0x%x]", priority, stream_type, ret);
        } else {
                for (i = 0; i < AVAIL_STREAMS_MAX; i++) {
                        if (g_stream_list.stream_types[i] &&
@@ -155,9 +161,9 @@ static int _mm_sound_mgr_focus_get_priority_from_stream_type(int *priority, cons
                }
                if (i == AVAIL_STREAMS_MAX) {
                        ret = MM_ERROR_NOT_SUPPORT_API;
-                       debug_error("not supported stream_type[%s], ret[0x%x]\n", stream_type, ret);
+                       debug_error("not supported stream_type[%s], ret[0x%x]", stream_type, ret);
                } else {
-                       debug_log("[%s] has priority of [%d]\n", stream_type, *priority);
+                       debug_log("[%s] has priority of [%d]", stream_type, *priority);
                }
        }
 
@@ -165,8 +171,53 @@ static int _mm_sound_mgr_focus_get_priority_from_stream_type(int *priority, cons
        return ret;
 }
 
-static int _mm_sound_mgr_focus_do_watch_callback(focus_type_e focus_type, focus_command_e command, focus_node_t *my_node, const _mm_sound_mgr_focus_param_t *param)
+static bool _check_session_node_exist(int pid)
+{
+       GList *list = NULL;
+       focus_node_t *node = NULL;
+
+       for (list = g_focus_node_list; list != NULL; list = list->next) {
+               node = (focus_node_t *)list->data;
+               if (node->pid != pid)
+                       continue;
+               if (node->is_for_monitor)
+                       continue;
+               if (node->is_for_session)
+                       return true;
+       }
+
+       debug_msg("session node for pid[%d] does not exist", pid);
+
+       return false;
+}
+
+static bool _check_session_watch_node_exist(int pid)
+{
+       GList *list = NULL;
+       focus_node_t *node = NULL;
+
+       for (list = g_focus_node_list; list != NULL; list = list->next) {
+               node = (focus_node_t *)list->data;
+               if (node->pid != pid)
+                       continue;
+               if (!node->is_for_watch)
+                       continue;
+               if (node->is_for_monitor)
+                       continue;
+               if (node->is_for_session)
+                       return true;
+       }
+
+       debug_msg("session watch node for pid[%d] does not exist", pid);
+
+       return false;
+}
+
+static void _invoke_watch_callback(focus_node_t *node, const char *stream_type, focus_type_e focus_type, focus_command_e command, const _mm_sound_mgr_focus_param_t *param)
 {
+       int ret = -1;
+       int pret = 0;
+       struct pollfd pfd;
        char *filename = NULL;
        char *filename2 = NULL;
        struct timeval time;
@@ -174,139 +225,222 @@ static int _mm_sound_mgr_focus_do_watch_callback(focus_type_e focus_type, focus_
        int endtime = 0;
        int fd_FOCUS_R = -1;
        int fd_FOCUS = -1;
-       int ret = -1;
-       struct pollfd pfd;
-       int pret = 0;
+       focus_cb_data cb_data;
+
+       if (!node || !stream_type) {
+               debug_error("[CB] invalid argument, node[%p], stream_type[%s]", node, stream_type);
+               return;
+       }
+
+       memset(&cb_data, 0, sizeof(focus_cb_data));
+       cb_data.pid = node->pid;
+       cb_data.handle = node->handle_id;
+       cb_data.type = focus_type & node->status;
+       cb_data.state = (command == FOCUS_COMMAND_ACQUIRE) ? !FOCUS_STATUS_DEACTIVATED : FOCUS_STATUS_DEACTIVATED;
+       MMSOUND_STRNCPY(cb_data.stream_type, stream_type, MAX_STREAM_TYPE_LEN);
+       MMSOUND_STRNCPY(cb_data.ext_info, param->ext_info, MM_SOUND_NAME_NUM);
+       node->during_cb = true;
+
+       /* Set start time */
+       gettimeofday(&time, NULL);
+       starttime = time.tv_sec * 1000000 + time.tv_usec;
+
+       /**************************************
+        *
+        * Open callback cmd pipe
+        *
+        **************************************/
+       filename = __get_focus_pipe_path(cb_data.pid, cb_data.handle, NULL, true);
+       if (filename == NULL) {
+               debug_error("[CB] failed to get watch pipe");
+               goto RELEASE;
+       }
+       if ((fd_FOCUS = open(filename, O_WRONLY|O_NONBLOCK)) == -1) {
+               char str_error[256];
+               strerror_r(errno, str_error, sizeof(str_error));
+               debug_error("[CB] failed to open watch pipe (%s, err:%s)", filename, str_error);
+               goto RELEASE;
+       }
+
+       /******************************************
+        *
+        * Open callback result pipe
+        * before writing callback cmd to pipe
+        *
+        ******************************************/
+        filename2 = __get_focus_pipe_path(cb_data.pid, cb_data.handle, "r", true);
+       if (filename2 == NULL) {
+               debug_error("[RETCB] failed to get watch return pipe");
+               goto RELEASE;
+       }
+       if ((fd_FOCUS_R= open(filename2, O_RDONLY|O_NONBLOCK)) == -1) {
+               char str_error[256];
+               strerror_r(errno, str_error, sizeof(str_error));
+               debug_error("[RETCB] failed to open watch return pipe (%s, err:%s)", filename2, str_error);
+               goto RELEASE;
+       }
+
+       /*******************************************
+        * Write Callback msg
+        *******************************************/
+       if (write(fd_FOCUS, &cb_data ,sizeof(cb_data)) == -1) {
+               char str_error[256];
+               strerror_r(errno, str_error, sizeof(str_error));
+               debug_error("[CB] failed to write (err:%s)", str_error);
+               goto RELEASE;
+       }
 
+       /*********************************************
+        *
+        * Wait callback result msg
+        *
+        ********************************************/
+       pfd.fd = fd_FOCUS_R;
+       pfd.events = POLLIN;
+       pfd.revents = 0;
+       debug_msg("[RETCB] wait WATCH CALLBACK (client pid=%d, cmd=%d, timeout=%d(ms))", cb_data.pid, command, CALLBACK_TIMEOUT);
+       pret = poll(&pfd, 1, CALLBACK_TIMEOUT);
+       if (pret < 0) {
+               debug_error("[RETCB] poll failed (%d)", pret);
+               goto RELEASE;
+       }
+       if (pfd.revents & POLLIN) {
+               if (read(fd_FOCUS_R, &ret, sizeof(ret)) == -1) {
+                       char str_error[256];
+                       strerror_r(errno, str_error, sizeof(str_error));
+                       debug_error("[RETCB] failed to read (err:%s)", str_error);
+                       goto RELEASE;
+               }
+       }
+
+       /* Calculate endtime and display*/
+       gettimeofday(&time, NULL);
+       endtime = time.tv_sec * 1000000 + time.tv_usec;
+       debug_msg("[RETCB] WATCH CALLBACK returned (cbtimelab=%d(ms), client pid=%d, return handle=%d)", ((endtime-starttime)/1000), cb_data.pid, ret);
+
+       /**************************************
+        *
+        * Close callback result pipe
+        *
+        **************************************/
+RELEASE:
+       node->during_cb = false;
+
+       g_free(filename);
+       filename = NULL;
+
+       g_free(filename2);
+       filename2 = NULL;
+
+       if (fd_FOCUS != -1) {
+               close(fd_FOCUS);
+               fd_FOCUS = -1;
+       }
+       if (fd_FOCUS_R != -1) {
+               close(fd_FOCUS_R);
+               fd_FOCUS_R = -1;
+       }
+}
+
+/* session backward compatibility for monitor handle */
+static int _mm_sound_mgr_focus_do_monitor_callback_outer(focus_type_e focus_type, focus_command_e command, focus_node_t *my_node, const _mm_sound_mgr_focus_param_t *param)
+{
        GList *list = NULL;
        focus_node_t *node = NULL;
-       focus_cb_data cb_data;
 
        debug_fenter();
 
+       if (!my_node) {
+               debug_error("[CB] my_node is null");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (node == my_node || (node->pid == my_node->pid && node->is_for_session && my_node->is_for_session)) {
-                       /* skip my own */
-               } else {
-                       if (node->is_for_watch && (node->status & focus_type)) {
-                               memset(&cb_data, 0, sizeof(focus_cb_data));
-                               cb_data.pid = node->pid;
-                               cb_data.handle = node->handle_id;
-                               cb_data.type = focus_type & node->status;
-                               cb_data.state = (command == FOCUS_COMMAND_ACQUIRE) ? !FOCUS_STATUS_DEACTIVATED : FOCUS_STATUS_DEACTIVATED;
-                               MMSOUND_STRNCPY(cb_data.stream_type, my_node->stream_type, MAX_STREAM_TYPE_LEN);
-                               MMSOUND_STRNCPY(cb_data.ext_info, param->ext_info, MM_SOUND_NAME_NUM);
-
-                               /* Set start time */
-                               gettimeofday(&time, NULL);
-                               starttime = time.tv_sec * 1000000 + time.tv_usec;
-
-                               /**************************************
-                                *
-                                * Open callback cmd pipe
-                                *
-                                **************************************/
-                               filename = __get_focus_pipe_path(cb_data.pid, cb_data.handle, NULL, true);
-                               if (filename == NULL) {
-                                       debug_error("[CB] failed to get watch pipe");
-                                       goto RELEASE;
-                               }
-                               if ((fd_FOCUS = open(filename, O_WRONLY|O_NONBLOCK)) == -1) {
-                                       char str_error[256];
-                                       strerror_r(errno, str_error, sizeof(str_error));
-                                       debug_error("[CB] failed to open watch pipe (%s, err:%s)\n", filename, str_error);
-                                       goto RELEASE;
-                               }
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               if (node == my_node)
+                       continue;
+               if (!node->is_for_watch || !node->is_for_monitor || !node->is_for_session)
+                       continue;
+               if (!(node->status & focus_type))
+                       continue;
+               /* check if it meets the condition to trigger monitor callback */
+               if (!_check_session_watch_node_exist(node->pid))
+                       continue;
+
+               _invoke_watch_callback(node, my_node->stream_type, focus_type, command, param);
+       }
 
-                               /******************************************
-                                *
-                                * Open callback result pipe
-                                * before writing callback cmd to pipe
-                                *
-                                ******************************************/
-                                filename2 = __get_focus_pipe_path(cb_data.pid, cb_data.handle, "r", true);
-                               if (filename2 == NULL) {
-                                       debug_error("[RETCB] failed to get watch return pipe");
-                                       goto RELEASE;
-                               }
-                               if ((fd_FOCUS_R= open(filename2, O_RDONLY|O_NONBLOCK)) == -1) {
-                                       char str_error[256];
-                                       strerror_r(errno, str_error, sizeof(str_error));
-                                       debug_error("[RETCB] failed to open watch return pipe (%s, err:%s)\n", filename2, str_error);
-                                       goto RELEASE;
-                               }
+       debug_fleave();
 
-                               /*******************************************
-                                * Write Callback msg
-                                *******************************************/
-                               if (write(fd_FOCUS, &cb_data ,sizeof(cb_data)) == -1) {
-                                       char str_error[256];
-                                       strerror_r(errno, str_error, sizeof(str_error));
-                                       debug_error("[CB] failed to write (err:%s)\n", str_error);
-                                       goto RELEASE;
-                               }
+       return MM_ERROR_NONE;
+}
 
-                               /*********************************************
-                                *
-                                * Wait callback result msg
-                                *
-                                ********************************************/
-                               pfd.fd = fd_FOCUS_R;
-                               pfd.events = POLLIN;
-                               pfd.revents = 0;
-                               debug_msg("[RETCB] wait WATCH CALLBACK (client pid=%d, cmd=%d, timeout=%d(ms))\n", cb_data.pid, command, CALLBACK_TIMEOUT);
-                               pret = poll(&pfd, 1, CALLBACK_TIMEOUT);
-                               if (pret < 0) {
-                                       debug_error("[RETCB] poll failed (%d)\n", pret);
-                                       goto RELEASE;
-                               }
-                               if (pfd.revents & POLLIN) {
-                                       if (read(fd_FOCUS_R, &ret, sizeof(ret)) == -1) {
-                                               char str_error[256];
-                                               strerror_r(errno, str_error, sizeof(str_error));
-                                               debug_error("[RETCB] failed to read (err:%s)\n", str_error);
-                                               goto RELEASE;
-                                       }
-                               }
+static int _mm_sound_mgr_focus_do_monitor_callback(focus_type_e focus_type, focus_command_e command, focus_node_t *my_node, const _mm_sound_mgr_focus_param_t *param)
+{
+       GList *list = NULL;
+       focus_node_t *node = NULL;
 
-                               /* Calculate endtime and display*/
-                               gettimeofday(&time, NULL);
-                               endtime = time.tv_sec * 1000000 + time.tv_usec;
-                               debug_msg("[RETCB] WATCH CALLBACK returned (cbtimelab=%d(ms), client pid=%d, return handle=%d)\n", ((endtime-starttime)/1000), cb_data.pid, ret);
+       debug_fenter();
 
-                               /**************************************
-                                *
-                                * Close callback result pipe
-                                *
-                                **************************************/
-RELEASE:
-                               if (filename) {
-                                       g_free (filename);
-                                       filename = NULL;
-                               }
-                               if (filename2) {
-                                       g_free (filename2);
-                                       filename2 = NULL;
-                               }
-                               if (fd_FOCUS != -1) {
-                                       close(fd_FOCUS);
-                                       fd_FOCUS = -1;
-                               }
-                               if (fd_FOCUS_R != -1) {
-                                       close(fd_FOCUS_R);
-                                       fd_FOCUS_R = -1;
-                               }
+       if (!my_node) {
+               debug_error("[CB] my_node is null");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
 
-                               continue;
-                       }
+       for (list = g_focus_node_list; list != NULL; list = list->next) {
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               if (!node->is_for_watch || !node->is_for_monitor || !node->is_for_session)
+                       continue;
+               if (node == my_node || !(node->pid == my_node->pid && my_node->is_for_session))
+                       continue;
+               if (!(node->status & focus_type))
+                       continue;
+               /* check if it meets the condition to trigger monitor callback */
+               if (!_check_session_node_exist(node->pid))
+                       continue;
+
+               _invoke_watch_callback(node, param->stream_type, focus_type, command, param);
+       }
+
+       debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
+static int _mm_sound_mgr_focus_do_watch_callback(focus_type_e focus_type, focus_command_e command, focus_node_t *my_node, const _mm_sound_mgr_focus_param_t *param)
+{
+       GList *list = NULL;
+       focus_node_t *node = NULL;
+
+       debug_fenter();
+
+       if (!my_node) {
+               debug_error("[CB] my_node is null");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       for (list = g_focus_node_list; list != NULL; list = list->next) {
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               if (node == my_node || (node->pid == my_node->pid && node->is_for_session && my_node->is_for_session))
+                       continue;
+               if (!node->is_for_watch || !(node->status & focus_type))
+                       continue;
+               if (node->is_for_monitor)
+                       continue;
+               if (node->during_cb) {
+                       debug_msg("it is about to invoke watch callback again during processing it, skip it");
+                       continue;
                }
+
+               _invoke_watch_callback(node, my_node->stream_type, focus_type, command, param);
        }
+
        debug_fleave();
+
        return MM_ERROR_NONE;
 }
 
-int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victim_node, const _mm_sound_mgr_focus_param_t *assaulter_param, const char *assaulter_stream_type)
+int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victim_node, const _mm_sound_mgr_focus_param_t *assaulter_param)
 {
        int res = MM_ERROR_NONE;
        char *filename = NULL;
@@ -330,7 +464,7 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
 
        focus_cb_data cb_data;
 
-       debug_error(" __mm_sound_mgr_focus_do_callback_ for pid(%d) handle(%d)\n", victim_node->pid, victim_node->handle_id);
+       debug_msg("for pid(%d) handle(%d)", victim_node->pid, victim_node->handle_id);
 
        memset(&cb_data, 0, sizeof(focus_cb_data));
        cb_data.pid= victim_node->pid;
@@ -363,7 +497,7 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
                        }
                }
        }
-       MMSOUND_STRNCPY(cb_data.stream_type, assaulter_stream_type, MAX_STREAM_TYPE_LEN);
+       MMSOUND_STRNCPY(cb_data.stream_type, assaulter_param->stream_type, MAX_STREAM_TYPE_LEN);
        MMSOUND_STRNCPY(cb_data.ext_info, assaulter_param->ext_info, MM_SOUND_NAME_NUM);
        cb_data.option = assaulter_param->option;
 
@@ -385,7 +519,7 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
        if ((fd_FOCUS = open(filename, O_WRONLY|O_NONBLOCK)) == -1) {
                char str_error[256];
                strerror_r(errno, str_error, sizeof(str_error));
-               debug_error("[CB] failed to open pipe (%s, err:%s)\n", filename, str_error);
+               debug_error("[CB] failed to open pipe (%s, err:%s)", filename, str_error);
                res = -1;
                goto RELEASE;
        }
@@ -405,7 +539,7 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
        if ((fd_FOCUS_R = open(filename2,O_RDONLY|O_NONBLOCK)) == -1) {
                char str_error[256];
                strerror_r(errno, str_error, sizeof(str_error));
-               debug_error("[RETCB] failed to open return pipe (%s, err:%s)\n", filename2, str_error);
+               debug_error("[RETCB] failed to open return pipe (%s, err:%s)", filename2, str_error);
                res = -1;
                goto RELEASE;
        }
@@ -416,7 +550,7 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
        if (write(fd_FOCUS, &cb_data, sizeof(cb_data)) == -1) {
                char str_error[256];
                strerror_r(errno, str_error, sizeof(str_error));
-               debug_error("[CB] failed to write (err:%s)\n", str_error);
+               debug_error("[CB] failed to write (err:%s)", str_error);
                res = -1;
                goto RELEASE;
        }
@@ -429,10 +563,10 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
        pfd.fd = fd_FOCUS_R;
        pfd.events = POLLIN;
        pfd.revents = 0;
-       debug_msg("[RETCB] wait CALLBACK (client pid=%d, handle=%d, cmd=%d, timeout=%d(ms))\n",cb_data.pid, cb_data.handle, command, CALLBACK_TIMEOUT);
+       debug_msg("[RETCB] wait CALLBACK (client pid=%d, handle=%d, cmd=%d, timeout=%d(ms))",cb_data.pid, cb_data.handle, command, CALLBACK_TIMEOUT);
        pret = poll(&pfd, 1, CALLBACK_TIMEOUT);
        if (pret < 0) {
-               debug_error("[RETCB] poll failed (%d)\n", pret);
+               debug_error("[RETCB] poll failed (%d)", pret);
                res = -1;
                goto RELEASE;
        }
@@ -440,7 +574,7 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
                if (read(fd_FOCUS_R, &ret, sizeof(ret)) == -1) {
                        char str_error[256];
                        strerror_r(errno, str_error, sizeof(str_error));
-                       debug_error("[RETCB] failed to read (err:%s)\n", str_error);
+                       debug_error("[RETCB] failed to read (err:%s)", str_error);
                        res = -1;
                        goto RELEASE;
                }
@@ -450,14 +584,14 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
                if (victim_node->reacquisition != (bool)((ret >> 16) & 0xf)) {
                        reacquisition_changed = true;
                        victim_node->reacquisition = (bool)((ret >> 16) & 0xf);
-                       debug_error("[RETCB] victim's reacquisition is changed to (%d)\n", victim_node->reacquisition);
+                       debug_msg("[RETCB] victim's reacquisition is changed to (%d)", victim_node->reacquisition);
                }
        }
 
        /* Calculate endtime and display*/
        gettimeofday(&time, NULL);
        endtime = time.tv_sec * 1000000 + time.tv_usec;
-       debug_msg("[RETCB] CALLBACK returned (cbtimelab=%d(ms), client pid=%d, returned handle=%d)\n", ((endtime-starttime)/1000), cb_data.pid, ret_handle);
+       debug_msg("[RETCB] CALLBACK returned (cbtimelab=%d(ms), client pid=%d, returned handle=%d)", ((endtime-starttime)/1000), cb_data.pid, ret_handle);
 
        /* update victim node */
        if (command == FOCUS_COMMAND_RELEASE) {
@@ -485,8 +619,8 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
                        if (reacquisition_changed) {
                                if (!victim_node->reacquisition) {
                                        for (list = g_focus_node_list; list != NULL; list = list->next) {
-                                               node = (focus_node_t *)list->data;
-                                               if (node && (node->taken_by_id[i].pid == victim_node->pid)) {
+                                               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+                                               if (node->taken_by_id[i].pid == victim_node->pid) {
                                                        UPDATE_FOCUS_TAKEN_INFO(backup, node, node->taken_by_id[i].pid, node->taken_by_id[i].handle_id, node->taken_by_id[i].by_session);
                                                        UPDATE_FOCUS_TAKEN_INFO(by_id, node, taken_pid, taken_hid, taken_by_session);
                                                } else if (!list->next) {
@@ -496,8 +630,8 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
                                        }
                                } else {
                                        for (list = g_focus_node_list; list != NULL; list = list->next) {
-                                               node = (focus_node_t *)list->data;
-                                               if (node && (node->taken_backup[i].pid == victim_node->pid)) {
+                                               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+                                               if (node->taken_backup[i].pid == victim_node->pid) {
                                                        UPDATE_FOCUS_TAKEN_INFO(by_id, node, node->taken_backup[i].pid, node->taken_backup[i].handle_id, node->taken_backup[i].by_session);
                                                        UPDATE_FOCUS_TAKEN_INFO(backup, node, 0, 0, false);
                                                } else if (!list->next) {
@@ -515,20 +649,22 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
                }
        }
 
-       victim_node->status = (command == FOCUS_COMMAND_RELEASE) ? (victim_node->status & ~(cb_data.type)) : (victim_node->status | cb_data.type);
+       if (command == FOCUS_COMMAND_RELEASE || victim_node->reacquisition_with_released_state)
+               victim_node->status = victim_node->status & ~(cb_data.type);
+       else if (command == FOCUS_COMMAND_ACQUIRE)
+               victim_node->status = victim_node->status | cb_data.type;
 
-       if (strncmp(assaulter_stream_type, victim_node->stream_type, MAX_STREAM_TYPE_LEN))
+       if (strncmp(assaulter_param->stream_type, victim_node->stream_type, MAX_STREAM_TYPE_LEN))
                _mm_sound_mgr_focus_do_watch_callback((focus_type_e)assaulter_param->request_type, command, victim_node, assaulter_param);
+       _mm_sound_mgr_focus_do_monitor_callback((focus_type_e)assaulter_param->request_type, command, victim_node, assaulter_param);
 
 RELEASE:
-       if (filename) {
-               g_free (filename);
-               filename = NULL;
-       }
-       if (filename2) {
-               g_free (filename2);
-               filename2 = NULL;
-       }
+       g_free(filename);
+       filename = NULL;
+
+       g_free(filename2);
+       filename2 = NULL;
+
        if (fd_FOCUS != -1) {
                close(fd_FOCUS);
                fd_FOCUS = -1;
@@ -547,17 +683,16 @@ static int _mm_sound_mgr_focus_list_dump ()
        GList *list = NULL;
        focus_node_t *node = NULL;
 
-       debug_log("================================================ focus node list : start ===================================================\n");
+       debug_msg("================================================ focus node list : start ===================================================");
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (node && !node->is_for_watch) {
-                       debug_log("*** pid[%5d]/handle_id[%2d]/[%14s]:priority[%2d],status[%s],taken_by[P(%5d/%2d/%2d)C(%5d/%2d/%2d)],session[%d],option[0x%x/0x%x],ext_info[%s/%s]\n",
-                                       node->pid, node->handle_id, node->stream_type, node->priority, focus_status_str[node->status],
-                                       node->taken_by_id[0].pid, node->taken_by_id[0].handle_id, node->taken_by_id[0].by_session, node->taken_by_id[1].pid,
-                                       node->taken_by_id[1].handle_id, node->taken_by_id[1].by_session, node->is_for_session, node->option[0], node->option[1], node->ext_info[0], node->ext_info[1]);
+               if ((node = (focus_node_t *)list->data) && !node->is_for_watch) {
+                       debug_msg("*** pid[%5d]/handle_id[%2d]/[%14s]:priority[%2d],status[%s],taken_by[P(%5d/%2d/%2d)C(%5d/%2d/%2d)],session[%d],option[0x%x/0x%x],ext_info[%s/%s]",
+                                 node->pid, node->handle_id, node->stream_type, node->priority, focus_status_str[node->status],
+                                 node->taken_by_id[0].pid, node->taken_by_id[0].handle_id, node->taken_by_id[0].by_session, node->taken_by_id[1].pid,
+                                 node->taken_by_id[1].handle_id, node->taken_by_id[1].by_session, node->is_for_session, node->option[0], node->option[1], node->ext_info[0], node->ext_info[1]);
                }
        }
-       debug_log("================================================ focus node list : end =====================================================\n");
+       debug_msg("================================================ focus node list : end =====================================================");
 
        return ret;
 }
@@ -568,14 +703,13 @@ static int _mm_sound_mgr_focus_watch_list_dump()
        GList *list = NULL;
        focus_node_t *node = NULL;
 
-       debug_log("============================================= focus watch node list : start =================================================\n");
+       debug_msg("============================================= focus watch node list : start =================================================");
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (node && node->is_for_watch) {
-                       debug_log("*** pid[%5d]/handle_id[%d]/watch on focus status[%s]/for_session[%d]\n", node->pid, node->handle_id, focus_status_str[node->status], node->is_for_session);
-               }
+               if ((node = (focus_node_t *)list->data) && node->is_for_watch)
+                       debug_msg("*** pid[%5d]/handle_id[%d]/watch on focus status[%s]/for_session[%d]/for_monitor[%d]",
+                                 node->pid, node->handle_id, focus_status_str[node->status], node->is_for_session, node->is_for_monitor);
        }
-       debug_log("============================================= focus watch node list : end ===================================================\n");
+       debug_msg("============================================= focus watch node list : end ===================================================");
 
        return ret;
 }
@@ -608,12 +742,12 @@ int mm_sound_mgr_focus_create_node(const _mm_sound_mgr_focus_param_t *param)
        g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
 
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (CHECK_MY_NODE(node, param)) {
-                       debug_error("the node of pid[%d]/handle_id[%d] is already created\n", param->pid, param->handle_id);
-                       ret = MM_ERROR_INVALID_ARGUMENT;
-                       goto FINISH;
-               }
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               CONTINUE_IF_NOT_MY_FOCUS_NODE(node, param);
+
+               debug_error("the node of pid[%d]/handle_id[%d] is already created", param->pid, param->handle_id);
+               ret = MM_ERROR_INVALID_ARGUMENT;
+               goto FINISH;
        }
 
        /* get priority from stream type */
@@ -632,9 +766,9 @@ int mm_sound_mgr_focus_create_node(const _mm_sound_mgr_focus_param_t *param)
 
        g_focus_node_list = g_list_append(g_focus_node_list, node);
        if (g_focus_node_list) {
-               debug_log("new focus node is added\n");
+               debug_log("new focus node is added");
        } else {
-               debug_error("g_list_append failed\n");
+               debug_error("g_list_append failed");
                ret = MM_ERROR_SOUND_INTERNAL;
                g_free(node);
        }
@@ -664,74 +798,92 @@ int mm_sound_mgr_focus_destroy_node(const _mm_sound_mgr_focus_param_t *param)
        g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
 
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (CHECK_MY_NODE(node, param)) {
-                       debug_log("found the node of pid[%d]/handle_id[%d]\n", param->pid, param->handle_id);
-                       my_node = node;
-                       break;
-               }
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               CONTINUE_IF_NOT_MY_FOCUS_NODE(node, param);
+
+               debug_log("found the node of pid[%d]/handle_id[%d]", param->pid, param->handle_id);
+               my_node = node;
+               break;
        }
        if (my_node == NULL) {
-               debug_error("could not find any node of pid[%d]/handle_id[%d]\n", param->pid, param->handle_id);
+               debug_error("could not find any node of pid[%d]/handle_id[%d]/is_for_session[%d]", param->pid, param->handle_id, param->is_for_session);
                ret = MM_ERROR_INVALID_ARGUMENT;
                goto FINISH;
        }
 
-       /* Check if there's remaining focus for session for the same PID of incomming param*/
+       /* Check if there's remaining focus for session for the same PID of incomming param */
        if (my_node->is_for_session) {
                for (list = g_focus_node_list; list != NULL; list = list->next) {
-                       node = (focus_node_t *)list->data;
-                       if (!node) {
-                               /* skip */
-                       } else if (my_node == node || node->is_for_watch) {
-                               /* skip */
-                       } else {
-                               if (node->pid == my_node->pid && node->is_for_session) {
-                                       debug_error("focus for session for this pid still remains, skip updating victim focus nodes");
-                                       need_to_trigger = false;
-                                       break;
-                               }
+                       CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+                       if (my_node == node || node->is_for_watch)
+                               continue;
+                       if (node->pid == my_node->pid && node->is_for_session && node->status) {
+                               debug_warning("another focus node for session of this pid exists, skip invoking callback");
+                               need_to_trigger = false;
+                               break;
                        }
                }
        }
 
        if (need_to_trigger) {
+               bool need_to_trigger_watch_cb = true;
+               _mm_sound_mgr_focus_param_t *new_param = NULL;
+
+               if (!(new_param = g_malloc0(sizeof(_mm_sound_mgr_focus_param_t)))) {
+                       debug_error("Fail to g_malloc0 for new_param");
+                       goto CLEAR_NODE;
+               }
+               new_param->pid = param->pid;
+               new_param->handle_id = param->handle_id;
+               new_param->is_for_session = my_node->is_for_session;
+               new_param->request_type = my_node->status;
+               new_param->option = my_node->option[i];
+               MMSOUND_STRNCPY(new_param->stream_type, my_node->stream_type, MAX_STREAM_TYPE_LEN);
+               MMSOUND_STRNCPY(new_param->ext_info, my_node->ext_info[i], MM_SOUND_NAME_NUM);
+
                for (list = g_focus_node_list; list != NULL; list = list->next) {
-                       node = (focus_node_t *)list->data;
-                       if (!node) {
-                               /* skip */
-                       } else if (my_node == node || node->is_for_watch) {
-                               /* skip */
-                       } else {
-                               for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
-                                       if (node->taken_by_id[i].pid == param->pid) {
-                                               if (my_node->taken_by_id[i].pid) {
-                                               /* If exists update the taken focus info to my victim node */
-                                                       if (node->taken_by_id[i].by_session && !node->status) {
-                                                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, my_node->taken_by_id[i].pid, my_node->taken_by_id[i].handle_id, my_node->taken_by_id[i].by_session);
-                                                       } else if (node->taken_by_id[i].handle_id == param->handle_id) {
-                                                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, my_node->taken_by_id[i].pid, my_node->taken_by_id[i].handle_id, false);
-                                                       }
-                                               } else {
-                                                       if (node->taken_by_id[i].by_session && !node->status) {
-                                                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, 0, 0, false);
-                                                       } else if (node->taken_by_id[i].handle_id == param->handle_id) {
-                                                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, 0, 0, false);
-                                                       }
+                       CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+                       if (my_node == node || node->is_for_watch)
+                               continue;
+                       for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
+                               if (node->taken_by_id[i].pid != param->pid)
+                                       continue;
+
+                               if (my_node->taken_by_id[i].pid) {
+                               /* If exists update the taken focus info to my victim node */
+                                       if (node->taken_by_id[i].by_session && !node->status) {
+                                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, my_node->taken_by_id[i].pid, my_node->taken_by_id[i].handle_id, my_node->taken_by_id[i].by_session);
+                                       } else if (node->taken_by_id[i].handle_id == param->handle_id) {
+                                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, my_node->taken_by_id[i].pid, my_node->taken_by_id[i].handle_id, false);
+                                       }
+                               } else if (my_node->status & (i+1)) {
+                                       if (node->is_for_session)
+                                               continue;
+                                       if (node->taken_by_id[i].handle_id == new_param->handle_id || node->taken_by_id[i].by_session) {
+                                               /* do callback for resumption */
+                                               if ((ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_ACQUIRE, node, new_param)))
+                                                       debug_error("Fail to _focus_do_callback for COMMAND ACQUIRE to node[%x], ret[0x%x]", node, ret);
+                                               if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN)) {
+                                                       need_to_trigger_watch_cb = false;
+                                                       my_node->status &= ~(new_param->request_type);
                                                }
                                        }
                                }
                        }
                }
+               if (need_to_trigger_watch_cb)
+                       _mm_sound_mgr_focus_do_watch_callback((focus_type_e)new_param->request_type, FOCUS_COMMAND_RELEASE, my_node, new_param);
+
+               g_free(new_param);
        }
 
+CLEAR_NODE:
        /* Destroy my node  */
        __clear_focus_pipe(my_node);
        g_focus_node_list = g_list_remove(g_focus_node_list, my_node);
        g_free(my_node);
-
-       _mm_sound_mgr_focus_list_dump();
 FINISH:
+       _mm_sound_mgr_focus_list_dump();
        MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
 
        debug_fleave();
@@ -755,29 +907,29 @@ int mm_sound_mgr_focus_set_reacquisition(const _mm_sound_mgr_focus_param_t *para
 
        /* Find node to set reacquisition */
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (CHECK_MY_NODE(node, param)) {
-                       if (node->reacquisition == param->reacquisition) {
-                               debug_msg("it is already set as same value of reacquisition(%d)\n", param->reacquisition);
-                               goto FINISH;
-                       }
-                       node->reacquisition = param->reacquisition;
-                       debug_msg("found a node to set reacquisition to (%d)\n", param->reacquisition);
-                       my_node = node;
-                       break;
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               CONTINUE_IF_NOT_MY_FOCUS_NODE(node, param);
+
+               if (node->reacquisition == param->reacquisition) {
+                       debug_msg("it is already set as same value of reacquisition(%d)", param->reacquisition);
+                       goto FINISH;
                }
+               node->reacquisition = param->reacquisition;
+               debug_msg("found a node(pid[%d]/handle_id[%d]) to set reacquisition to (%d)", node->pid, node->handle_id, param->reacquisition);
+               my_node = node;
+               break;
        }
        if (my_node == NULL) {
-               debug_error("could not find any node of pid[%d]/handle_id[%d]\n", param->pid, param->handle_id);
+               debug_error("could not find any node of pid[%d]/handle_id[%d]", param->pid, param->handle_id);
                ret = MM_ERROR_INVALID_ARGUMENT;
                goto FINISH;
        }
 
        if (!param->reacquisition) {
                for (list = g_focus_node_list; list != NULL; list = list->next) {
-                       node = (focus_node_t *)list->data;
+                       CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
                        for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
-                               if (node && (node->taken_by_id[i].pid == param->pid)) {
+                               if (node->taken_by_id[i].pid == param->pid) {
                                        /* victim node : append my node's taken info to my victim node */
                                        if (my_node->taken_by_id[i].pid != 0) {
                                                UPDATE_FOCUS_TAKEN_INFO(backup, node, node->taken_by_id[i].pid, node->taken_by_id[i].handle_id, node->taken_by_id[i].by_session);
@@ -792,10 +944,10 @@ int mm_sound_mgr_focus_set_reacquisition(const _mm_sound_mgr_focus_param_t *para
                }
        } else {
                for (list = g_focus_node_list; list != NULL; list = list->next) {
-                       node = (focus_node_t *)list->data;
+                       CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
                        for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
                                /* rollback and reset backup info. */
-                               if (node && (node->taken_backup[i].pid == param->pid)) {
+                               if (node->taken_by_id[i].pid && (node->taken_by_id[i].pid == my_node->taken_backup[i].pid)) {
                                        UPDATE_FOCUS_TAKEN_INFO(by_id, node, node->taken_backup[i].pid, node->taken_backup[i].handle_id, node->taken_backup[i].by_session);
                                        UPDATE_FOCUS_TAKEN_INFO(backup, node, 0, 0, false);
                                } else if (!list->next) {
@@ -822,9 +974,7 @@ int mm_sound_mgr_focus_get_stream_type_of_acquired_focus(focus_type_e focus_type
 
        debug_fenter();
 
-       if (focus_type == FOCUS_TYPE_BOTH) /* focus_type should be "playback" or "capture" */
-               return MM_ERROR_INVALID_ARGUMENT;
-       if (!stream_type)
+       if (!stream_type || !option)
                return MM_ERROR_INVALID_ARGUMENT;
 
        MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
@@ -834,13 +984,21 @@ int mm_sound_mgr_focus_get_stream_type_of_acquired_focus(focus_type_e focus_type
 
        /* Find node to set reacquisition */
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (node && !node->is_for_watch && (node->status & focus_type)) {
-                       debug_msg("found a node : request_focus_type(%d), stream_type(%s)/ext info(%s) of acquired focus\n", focus_type, node->stream_type, node->ext_info);
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               if (!node->is_for_watch && (node->status & focus_type)) {
+                        /* In case of FOCUS_TYPE_BOTH, we use index for FOCUS_TYPE_PLAYBACK's forcedly.
+                         * It is because this function can not return both index of option, ext_info results
+                         * via out-parameter. This case is only used in framework internally for session
+                         * backward compatibilty. */
+                       int index = (focus_type == FOCUS_TYPE_BOTH) ? FOCUS_TYPE_PLAYBACK - 1 : focus_type - 1;
+
+                       debug_msg("found a node : request_focus_type(%d), stream_type(%s)/ext info(%s) of acquired focus",
+                                 focus_type, node->stream_type, node->ext_info[index]);
+
                        *stream_type = node->stream_type;
-                       *option = node->option[focus_type-1];
+                       *option = node->option[index];
                        if (ext_info)
-                               *ext_info = node->ext_info[focus_type-1];
+                               *ext_info = node->ext_info[index];
                        ret = MM_ERROR_NONE;
                        break;
                }
@@ -853,6 +1011,28 @@ int mm_sound_mgr_focus_get_stream_type_of_acquired_focus(focus_type_e focus_type
        return ret;
 }
 
+static void update_reacquisition_with_released_state(focus_node_t *node, int direction)
+{
+       if (!node) {
+               debug_error("node is null");
+               return;
+       }
+       if (direction >= NUM_OF_STREAM_IO_TYPE) {
+               debug_error("invalid direction(%d)", direction);
+               return;
+       }
+
+       /* In case of session backward compatibility for audio-io, mm-player, mm-camcorder, we mark a specific flag here.
+        When invoking focus state changed callback for acquiring, state of the node will not be updated rather updated
+        when the next request to acquire. */
+       if (!strncmp("audio-io acquire focus", node->ext_info[direction], MM_SOUND_NAME_NUM) ||
+           !strncmp("mm-player acquire focus", node->ext_info[direction], MM_SOUND_NAME_NUM) ||
+           !strncmp("mm-camcorder acquire focus", node->ext_info[direction], MM_SOUND_NAME_NUM)) {
+               debug_msg("this node[pid:%d, handle_id:%d] needs reacquisition with focus released state", node->pid, node->handle_id);
+               node->reacquisition_with_released_state = true;
+       }
+}
+
 int mm_sound_mgr_focus_request_acquire(const _mm_sound_mgr_focus_param_t *param)
 {
        int ret = MM_ERROR_NONE;
@@ -861,24 +1041,26 @@ int mm_sound_mgr_focus_request_acquire(const _mm_sound_mgr_focus_param_t *param)
        focus_node_t *my_node = NULL;
        bool need_to_trigger_cb = false;
        bool need_to_trigger_watch_cb = true;
+       bool need_to_trigger_monitor_cb = true;
        int i;
 
        debug_fenter();
 
-       MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
+       if (!param->is_in_thread)
+               MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
 
        /* Update list for dead process */
        g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
 
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (CHECK_MY_NODE(node, param)) {
-                       my_node = node;
-                       if ((my_node->status > FOCUS_STATUS_DEACTIVATED) && (my_node->status & param->request_type)) {
-                               debug_error("focus status is already activated");
-                               ret = MM_ERROR_SOUND_INVALID_STATE;
-                               goto FINISH;
-                       }
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               CONTINUE_IF_NOT_MY_FOCUS_NODE(node, param);
+
+               my_node = node;
+               if ((my_node->status > FOCUS_STATUS_DEACTIVATED) && (my_node->status & param->request_type)) {
+                       debug_error("focus status is already activated");
+                       ret = MM_ERROR_SOUND_INVALID_STATE;
+                       goto FINISH;
                }
        }
 
@@ -890,21 +1072,20 @@ int mm_sound_mgr_focus_request_acquire(const _mm_sound_mgr_focus_param_t *param)
 
        /* check if the priority of any node is higher than its based on io direction */
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (!node) {
-                       /* skip */
-               } else if (my_node == node || node->is_for_watch) {
-                       /* skip */
-               } else if (param->request_type == FOCUS_TYPE_BOTH || node->status == FOCUS_STATUS_ACTIVATED_BOTH ||
-                                       (node->status & param->request_type)) {
-                       if (node->status > FOCUS_STATUS_DEACTIVATED) {
-                               if ((my_node->priority < node->priority)) {
-                                       ret = MM_ERROR_POLICY_BLOCKED;
-                                       need_to_trigger_cb = false;
-                                       break;
-                               } else {
-                                       need_to_trigger_cb = true;
-                               }
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               if (my_node == node || node->is_for_watch)
+                       continue;
+               if (param->request_type == FOCUS_TYPE_BOTH || node->status == FOCUS_STATUS_ACTIVATED_BOTH ||
+                       (node->status & param->request_type)) {
+                       if (node->status <= FOCUS_STATUS_DEACTIVATED)
+                               continue;
+
+                       if ((my_node->priority < node->priority)) {
+                               ret = MM_ERROR_POLICY_BLOCKED;
+                               need_to_trigger_cb = false;
+                               break;
+                       } else {
+                               need_to_trigger_cb = true;
                        }
                }
        }
@@ -912,27 +1093,28 @@ int mm_sound_mgr_focus_request_acquire(const _mm_sound_mgr_focus_param_t *param)
        if (need_to_trigger_cb) {
                _mm_sound_mgr_focus_param_t *param_s = (_mm_sound_mgr_focus_param_t *)param;
                param_s->is_for_session = my_node->is_for_session;
+               MMSOUND_STRNCPY(param_s->stream_type, my_node->stream_type, MAX_STREAM_TYPE_LEN);
                for (list = g_focus_node_list; list != NULL; list = list->next) {
-                       node = (focus_node_t *)list->data;
-                       if (!node) {
-                               /* skip */
-                       } else if (node == my_node || node->is_for_watch || (node->pid == my_node->pid && node->is_for_session && my_node->is_for_session)) {
-                               /* skip */
-                       } else if (param_s->request_type == FOCUS_TYPE_BOTH || node->status == FOCUS_STATUS_ACTIVATED_BOTH ||
-                                       (node->status & param_s->request_type)) {
-                               if (node->status > FOCUS_STATUS_DEACTIVATED) {
-                                       if (my_node->priority >= node->priority) {
-                                               /* do callback for interruption */
-                                               ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_RELEASE, node, param_s, my_node->stream_type);
-                                               if (ret) {
-                                                       debug_error("Fail to _focus_do_callback for COMMAND RELEASE to node[%x], ret[0x%x]\n", node, ret);
-                                                       /* but, keep going */
-                                                       ret = MM_ERROR_NONE;
-                                               }
-                                               if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN)) {
-                                                       need_to_trigger_watch_cb = false;
-                                               }
+                       CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+                       if (node == my_node || node->is_for_watch)
+                               continue;
+                       if (node->pid == my_node->pid && node->is_for_session && my_node->is_for_session)
+                               continue;
+                       if (param_s->request_type == FOCUS_TYPE_BOTH || node->status == FOCUS_STATUS_ACTIVATED_BOTH ||
+                               (node->status & param_s->request_type)) {
+                               if (node->status <= FOCUS_STATUS_DEACTIVATED)
+                                       continue;
+                               if (my_node->priority >= node->priority) {
+                                       /* do callback for interruption */
+                                       if ((ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_RELEASE, node, param_s))) {
+                                               debug_error("Fail to _focus_do_callback for COMMAND RELEASE to node[%x], ret[0x%x]", node, ret);
+                                               /* but, keep going */
+                                               ret = MM_ERROR_NONE;
                                        }
+                                       if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN))
+                                               need_to_trigger_watch_cb = false;
+
+                                       need_to_trigger_monitor_cb = false;
                                }
                        }
                }
@@ -944,6 +1126,7 @@ int mm_sound_mgr_focus_request_acquire(const _mm_sound_mgr_focus_param_t *param)
                        if (param->request_type & (i+1)) {
                                MMSOUND_STRNCPY(my_node->ext_info[i], param->ext_info, MM_SOUND_NAME_NUM);
                                my_node->option[i] = param->option;
+                               update_reacquisition_with_released_state(my_node, i);
                        }
                }
                /* update status */
@@ -951,20 +1134,23 @@ int mm_sound_mgr_focus_request_acquire(const _mm_sound_mgr_focus_param_t *param)
                /* do watch callback due to the status of mine */
                if (need_to_trigger_watch_cb)
                        _mm_sound_mgr_focus_do_watch_callback((focus_type_e)param->request_type, FOCUS_COMMAND_ACQUIRE, my_node, param);
-       }
+               if (need_to_trigger_monitor_cb)
+                       _mm_sound_mgr_focus_do_monitor_callback_outer((focus_type_e)param->request_type, FOCUS_COMMAND_RELEASE, my_node, param);
 
-       /* update taken information */
-       for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
-               if (param->request_type & (i+1) && my_node->taken_by_id[i].pid) {
-                       UPDATE_FOCUS_TAKEN_INFO(by_id, my_node, 0, 0, false);
-                       UPDATE_FOCUS_TAKEN_INFO(backup, my_node, 0, 0, false);
+               /* update taken information */
+               for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
+                       if (param->request_type & (i+1)) {
+                               UPDATE_FOCUS_TAKEN_INFO(by_id, my_node, 0, 0, false);
+                               UPDATE_FOCUS_TAKEN_INFO(backup, my_node, 0, 0, false);
+                       }
                }
        }
 
        _mm_sound_mgr_focus_list_dump();
        _mm_sound_mgr_focus_watch_list_dump ();
 FINISH:
-       MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
+       if (!param->is_in_thread)
+               MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
 
        debug_fleave();
        return ret;
@@ -977,31 +1163,33 @@ int mm_sound_mgr_focus_request_release(const _mm_sound_mgr_focus_param_t *param)
        focus_node_t *node = NULL;
        focus_node_t *my_node = NULL;
        bool need_to_trigger_watch_cb = true;
+       bool need_to_trigger_monitor_cb = true;
        bool need_to_trigger_cb = true;
        int i = 0;
 
        debug_fenter();
 
-       MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
+       if (!param->is_in_thread)
+               MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
 
        /* Update list for dead process */
        g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
 
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (CHECK_MY_NODE(node, param)) {
-                       my_node = node;
-                       if (my_node->status == FOCUS_STATUS_DEACTIVATED) {
-                               debug_error("focus status is already deactivated");
-                               ret = MM_ERROR_SOUND_INVALID_STATE;
-                               goto FINISH;
-                       } else if ((my_node->status != FOCUS_STATUS_ACTIVATED_BOTH) && (my_node->status != (focus_status_e)param->request_type)) {
-                               debug_error("request type is not matched with current focus type");
-                               ret = MM_ERROR_SOUND_INVALID_STATE;
-                               goto FINISH;
-                       }
-                       break;
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               CONTINUE_IF_NOT_MY_FOCUS_NODE(node, param);
+
+               my_node = node;
+               if (my_node->status == FOCUS_STATUS_DEACTIVATED) {
+                       debug_error("focus status is already deactivated");
+                       ret = MM_ERROR_SOUND_INVALID_STATE;
+                       goto FINISH;
+               } else if ((my_node->status != FOCUS_STATUS_ACTIVATED_BOTH) && (my_node->status != (focus_status_e)param->request_type)) {
+                       debug_error("request type is not matched with current focus type");
+                       ret = MM_ERROR_SOUND_INVALID_STATE;
+                       goto FINISH;
                }
+               break;
        }
 
        if (my_node == NULL) {
@@ -1013,12 +1201,11 @@ int mm_sound_mgr_focus_request_release(const _mm_sound_mgr_focus_param_t *param)
        /* Check if there's activating focus for session for the same PID of incomming param*/
        if (my_node->is_for_session) {
                for (list = g_focus_node_list; list != NULL; list = list->next) {
-                       node = (focus_node_t *)list->data;
-                       if (!node) {
-                               /* skip */
-                       } else if (node != my_node && node->pid == my_node->pid && node->is_for_session && !node->is_for_watch
-                               && my_node->status & node->status) {
-                               debug_error("focus for session for this pid is active, skip callbacks");
+                       CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+                       if (node == my_node || node->is_for_watch)
+                               continue;
+                       if (node->pid == my_node->pid && node->is_for_session && node->status) {
+                               debug_warning("another focus node for session of this pid exists, skip invoking callback");
                                need_to_trigger_watch_cb = false;
                                need_to_trigger_cb = false;
                                break;
@@ -1029,25 +1216,28 @@ int mm_sound_mgr_focus_request_release(const _mm_sound_mgr_focus_param_t *param)
        if (need_to_trigger_cb) {
                _mm_sound_mgr_focus_param_t *param_s = (_mm_sound_mgr_focus_param_t *)param;
                param_s->is_for_session = my_node->is_for_session;
+               MMSOUND_STRNCPY(param_s->stream_type, my_node->stream_type, MAX_STREAM_TYPE_LEN);
                for (list = g_focus_node_list; list != NULL; list = list->next) {
-                       node = (focus_node_t *)list->data;
-                       if (!node) {
-                               /* skip */
-                       } else if (node == my_node || node->is_for_watch) {
-                               /* skip */
-                       } else {
-                               for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
-                                       if (param_s->request_type & (i+1)) {
-                                               if (node->taken_by_id[i].pid == param_s->pid && (node->taken_by_id[i].handle_id == param_s->handle_id || node->taken_by_id[i].by_session)) {
-                                                       /* do callback for resumption */
-                                                       ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_ACQUIRE, node, param_s, my_node->stream_type);
-                                                       if (ret) {
-                                                               debug_error("Fail to _focus_do_callback for COMMAND ACQUIRE to node[%x], ret[0x%x]\n", node, ret);
-                                                       }
-                                                       if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN)) {
-                                                               need_to_trigger_watch_cb = false;
-                                                       }
+                       CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+                       if (node == my_node || node->is_for_watch)
+                               continue;
+                       for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
+                               if (param_s->request_type & (i+1)) {
+                                       if (node->taken_by_id[i].pid == param_s->pid &&
+                                           (node->taken_by_id[i].handle_id == param_s->handle_id || node->taken_by_id[i].by_session)) {
+                                               /* exception case as per the previous session policy,
+                                                * "session resumption" is only available for "media session" */
+                                               if (my_node->is_for_session && node->is_for_session) {
+                                                       if (strncmp(node->stream_type, "media", MAX_STREAM_TYPE_LEN))
+                                                               continue;
+                                               }
+                                               /* do callback for resumption */
+                                               if ((ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_ACQUIRE, node, param_s)))
+                                                       debug_error("Fail to _focus_do_callback for COMMAND ACQUIRE to node[%x], ret[0x%x]", node, ret);
+                                               if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN)) {
+                                                       need_to_trigger_watch_cb = false;
                                                }
+                                               need_to_trigger_monitor_cb = false;
                                        }
                                }
                        }
@@ -1065,11 +1255,14 @@ int mm_sound_mgr_focus_request_release(const _mm_sound_mgr_focus_param_t *param)
        /* do watch callback due to the status of mine */
        if (need_to_trigger_watch_cb)
                _mm_sound_mgr_focus_do_watch_callback((focus_type_e)param->request_type, FOCUS_COMMAND_RELEASE, my_node, param);
+       if (need_to_trigger_monitor_cb)
+               _mm_sound_mgr_focus_do_monitor_callback_outer((focus_type_e)param->request_type, FOCUS_COMMAND_ACQUIRE, my_node, param);
 
        _mm_sound_mgr_focus_list_dump();
        _mm_sound_mgr_focus_watch_list_dump ();
 FINISH:
-       MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
+       if (!param->is_in_thread)
+               MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
 
        debug_fleave();
        return ret;
@@ -1089,9 +1282,9 @@ int mm_sound_mgr_focus_set_watch_cb(const _mm_sound_mgr_focus_param_t *param)
        g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
 
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (node && (node->pid == param->pid) && (node->handle_id == param->handle_id) && node->is_for_watch) {
-                       debug_error("the node of pid[%d]/handle_id[%d] for watch focus is already created\n", param->pid, param->handle_id);
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               if ((node->pid == param->pid) && (node->handle_id == param->handle_id) && node->is_for_watch) {
+                       debug_error("the node of pid[%d]/handle_id[%d] for watch focus is already created", param->pid, param->handle_id);
                        ret = MM_ERROR_INVALID_ARGUMENT;
                        goto FINISH;
                }
@@ -1102,13 +1295,14 @@ int mm_sound_mgr_focus_set_watch_cb(const _mm_sound_mgr_focus_param_t *param)
        /* fill up information to the node */
        _mm_sound_mgr_focus_fill_info_from_msg(node, param);
        node->is_for_watch = true;
+       node->is_for_monitor = param->is_for_monitor;
        node->status = param->request_type;
 
        g_focus_node_list = g_list_append(g_focus_node_list, node);
        if (g_focus_node_list) {
-               debug_log("new focus node is added\n");
+               debug_log("new focus node is added");
        } else {
-               debug_error("g_list_append failed\n");
+               debug_error("g_list_append failed");
                ret = MM_ERROR_SOUND_INTERNAL;
                g_free(node);
        }
@@ -1135,9 +1329,9 @@ int mm_sound_mgr_focus_unset_watch_cb(const _mm_sound_mgr_focus_param_t *param)
        g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
 
        for (list = g_focus_node_list; list != NULL; list = list->next) {
-               node = (focus_node_t *)list->data;
-               if (node && (node->pid == param->pid) && (node->handle_id == param->handle_id) && (node->is_for_watch)) {
-                       debug_log("found the node of pid[%d]/handle_id[%d] for watch focus\n", param->pid, param->handle_id);
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               if ((node->pid == param->pid) && (node->handle_id == param->handle_id) && node->is_for_watch) {
+                       debug_log("found the node of pid[%d]/handle_id[%d] for watch focus", param->pid, param->handle_id);
                        __clear_focus_pipe(node);
                        g_focus_node_list = g_list_remove(g_focus_node_list, node);
                        g_free(node);
@@ -1146,7 +1340,7 @@ int mm_sound_mgr_focus_unset_watch_cb(const _mm_sound_mgr_focus_param_t *param)
                }
        }
        if (list == NULL) {
-               debug_error("could not find any node of pid[%d]/handle_id[%d] for watch focus\n", param->pid, param->handle_id);
+               debug_error("could not find any node of pid[%d]/handle_id[%d] for watch focus", param->pid, param->handle_id);
                ret = MM_ERROR_INVALID_ARGUMENT;
                goto FINISH;
        }
@@ -1159,6 +1353,101 @@ FINISH:
        return ret;
 }
 
+int mm_sound_mgr_focus_deliver(const _mm_sound_mgr_focus_param_t *param)
+{
+       int ret = MM_ERROR_NONE;
+       GList *list = NULL;
+       focus_node_t *src_node = NULL;
+       focus_node_t *dst_node = NULL;
+       int i = 0;
+
+       debug_fenter();
+
+       MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
+
+       /* Update list for dead process */
+       g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
+
+       for (list = g_focus_node_list; list != NULL; list = list->next) {
+               CONTINUE_IF_LIST_DATA_IS_NULL(src_node, list);
+               if ((src_node->pid == param->pid) && (src_node->handle_id == param->handle_id)) {
+                       debug_log("SRC: found the node of pid[%d]/handle_id[%d] for watch focus",
+                                 param->pid, param->handle_id);
+                       break;
+               }
+       }
+       if (src_node == NULL) {
+               debug_error("could not find the source node of param, pid[%d]/handle_id[%d]",
+                           param->pid, param->handle_id);
+               ret = MM_ERROR_INVALID_ARGUMENT;
+               goto FINISH;
+       }
+
+       if (!(src_node->status & param->request_type)) {
+               debug_error("invalid request type(0x%x), src_node->status(0x%x)",
+                           param->request_type, src_node->status);
+               ret = MM_ERROR_SOUND_INVALID_STATE;
+               goto FINISH;
+       }
+
+       for (list = g_focus_node_list; list != NULL; list = list->next) {
+               CONTINUE_IF_LIST_DATA_IS_NULL(dst_node, list);
+               if ((dst_node->pid == param->pid) && (dst_node->handle_id == param->handle_id_dst)) {
+                       debug_log("DST: found the destination node of param, pid[%d]/handle_id[%d]",
+                                 param->pid, param->handle_id_dst);
+                       break;
+               }
+       }
+       if (dst_node == NULL) {
+               debug_error("could not find the destination node of param, pid[%d]/handle_id[%d]",
+                           param->pid, param->handle_id_dst);
+               ret = MM_ERROR_INVALID_ARGUMENT;
+               goto FINISH;
+       }
+
+       for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
+               focus_node_t *node = NULL;
+               if (!(param->request_type & (i+1)))
+                       continue;
+
+               for (list = g_focus_node_list; list != NULL; list = list->next) {
+                       CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+                       if ((node->taken_by_id[i].pid == src_node->pid) &&
+                           (node->taken_by_id[i].handle_id == src_node->handle_id) &&
+                           (node->taken_by_id[i].by_session == false)) {
+                               debug_log("found the node that focus was taken by this src node, update it",
+                                         node->pid, node->handle_id);
+                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, dst_node->pid, dst_node->handle_id, false);
+                       }
+                       if ((node->taken_backup[i].pid == src_node->pid) &&
+                           (node->taken_backup[i].handle_id == src_node->handle_id) &&
+                           (node->taken_backup[i].by_session == false)) {
+                               debug_log("found the node that focus was taken by this src node and set reacquisition to false, update it",
+                                         node->pid, node->handle_id);
+                               UPDATE_FOCUS_TAKEN_INFO(backup, node, dst_node->pid, dst_node->handle_id, false);
+                       }
+               }
+
+               dst_node->status |= (i+1);
+               UPDATE_FOCUS_TAKEN_INFO(by_id, dst_node, 0, 0, false);
+               UPDATE_FOCUS_TAKEN_INFO(backup, dst_node, 0, 0, false);
+               MMSOUND_STRNCPY(dst_node->ext_info[i], src_node->ext_info[i], MM_SOUND_NAME_NUM);
+               dst_node->option[i] = src_node->option[i];
+
+               src_node->status &= ~(i+1);
+               memset(src_node->ext_info[i], 0x0, MM_SOUND_NAME_NUM);
+               src_node->option[i] = 0;
+       }
+
+       _mm_sound_mgr_focus_list_dump();
+
+FINISH:
+       MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
+
+       debug_fleave();
+       return ret;
+}
+
 int mm_sound_mgr_focus_emergent_exit(const _mm_sound_mgr_focus_param_t *param)
 {
        int ret = MM_ERROR_NONE;
@@ -1177,79 +1466,75 @@ int mm_sound_mgr_focus_emergent_exit(const _mm_sound_mgr_focus_param_t *param)
 
        list = g_focus_node_list;
        while (list) {
-               node = (focus_node_t *)list->data;
-               if (node && (node->pid == param->pid)) {
-                       debug_log("found pid node");
-                       if (node->is_for_watch) {
-                               debug_log("clearing watch cb of pid(%d) handle(%d)", node->pid, node->handle_id);
-                               __clear_focus_pipe(node);
-                               g_focus_node_list = g_list_remove(g_focus_node_list, node);
-                               list = g_focus_node_list;
-                               g_free(node);
-                       } else if (node->status == FOCUS_STATUS_DEACTIVATED) {
-                               debug_log("clearing deactivated focus node of pid(%d) hande(%d)", node->pid, node->handle_id);
-                               my_node = node;
-                               /* update info of nodes that are lost their focus by the process exited */
-                               for (list_s = g_focus_node_list; list_s != NULL; list_s = list_s->next) {
-                                       node = (focus_node_t *)list_s->data;
-                                       for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
-                                               if (node && (node->taken_by_id[i].pid == param->pid)) {
-                                                       if (my_node->taken_by_id[i].pid) {
-                                                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, my_node->taken_by_id[i].pid, my_node->taken_by_id[i].handle_id, my_node->taken_by_id[i].by_session);
-                                                       } else {
-                                                               UPDATE_FOCUS_TAKEN_INFO(by_id, node, 0, 0, false);
-                                                       }
-                                               }
-                                       }
-                               }
-                               __clear_focus_pipe(my_node);
-                               g_focus_node_list = g_list_remove(g_focus_node_list, my_node);
-                               list = g_focus_node_list;
-                               g_free(my_node);
-                       } else { /* node that acquired focus */
-                               bool need_to_trigger_watch_cb = true;
-                               _mm_sound_mgr_focus_param_t param_s;
-                               debug_log("clearing activated focus node of pid(%d) handle(%d)", node->pid, node->handle_id);
-
-                               my_node = node;
-                               memset(&param_s, 0x00, sizeof(_mm_sound_mgr_focus_param_t));
-                               param_s.pid = my_node->pid;
-                               param_s.handle_id = my_node->handle_id;
-                               param_s.request_type = my_node->status;
-                               for (list_s = g_focus_node_list; list_s != NULL; list_s = list_s->next) {
-                                       node = (focus_node_t *)list_s->data;
-                                       if (!node || my_node->pid == node->pid || node->is_for_watch) {
-                                               /* skip */
-                                       } else {
-                                               for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
-                                                       if (my_node->status & (i+1)) {
-                                                               if (node->taken_by_id[i].pid == param_s.pid && node->taken_by_id[i].handle_id == param_s.handle_id) {
-                                                                       /* do callback for resumption */
-                                                                       ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_ACQUIRE, node, &param_s, my_node->stream_type);
-                                                                       if (ret) {
-                                                                               debug_error("Fail to _focus_do_callback for COMMAND ACQUIRE to node[%x], ret[0x%x]\n", node, ret);
-                                                                       }
-                                                                       if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN)) {
-                                                                               need_to_trigger_watch_cb = false;
-                                                                       }
-                                                               }
-                                                       }
+               CONTINUE_IF_LIST_DATA_IS_NULL(node, list);
+               if (node->pid != param->pid) {
+                       list = list->next;
+                       debug_log("node not found, next list = %p",list);
+                       continue;
+               }
+               if (node->is_for_watch) {
+                       debug_log("clearing watch cb of pid(%d) handle(%d)", node->pid, node->handle_id);
+                       __clear_focus_pipe(node);
+                       g_focus_node_list = g_list_remove(g_focus_node_list, node);
+                       list = g_focus_node_list;
+                       g_free(node);
+                       continue;
+               }
+               if (node->status == FOCUS_STATUS_DEACTIVATED) {
+                       debug_log("clearing deactivated focus node of pid(%d) hande(%d)", node->pid, node->handle_id);
+                       my_node = node;
+                       /* update info of nodes that are lost their focus by the process exited */
+                       for (list_s = g_focus_node_list; list_s != NULL; list_s = list_s->next) {
+                               CONTINUE_IF_LIST_DATA_IS_NULL(node, list_s);
+                               for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
+                                       if (node->taken_by_id[i].pid == param->pid) {
+                                               if (my_node->taken_by_id[i].pid) {
+                                                       UPDATE_FOCUS_TAKEN_INFO(by_id, node, my_node->taken_by_id[i].pid, my_node->taken_by_id[i].handle_id, my_node->taken_by_id[i].by_session);
+                                               } else {
+                                                       UPDATE_FOCUS_TAKEN_INFO(by_id, node, 0, 0, false);
                                                }
                                        }
                                }
-                               if (need_to_trigger_watch_cb) {
-                                       ret = _mm_sound_mgr_focus_do_watch_callback((focus_type_e)param_s.request_type, FOCUS_COMMAND_RELEASE, my_node, &param_s);
-                                       if (ret) {
-                                               debug_error("Fail to _focus_do_watch_callback, ret[0x%x]\n", ret);
+                       }
+                       __clear_focus_pipe(my_node);
+                       g_focus_node_list = g_list_remove(g_focus_node_list, my_node);
+                       list = g_focus_node_list;
+                       g_free(my_node);
+               } else { /* node that acquired focus */
+                       bool need_to_trigger_watch_cb = true;
+                       _mm_sound_mgr_focus_param_t param_s;
+                       debug_log("clearing activated focus node of pid(%d) handle(%d)", node->pid, node->handle_id);
+
+                       my_node = node;
+                       memset(&param_s, 0x00, sizeof(_mm_sound_mgr_focus_param_t));
+                       param_s.pid = my_node->pid;
+                       param_s.handle_id = my_node->handle_id;
+                       param_s.request_type = my_node->status;
+                       MMSOUND_STRNCPY(param_s.stream_type, my_node->stream_type, MAX_STREAM_TYPE_LEN);
+                       for (list_s = g_focus_node_list; list_s != NULL; list_s = list_s->next) {
+                               CONTINUE_IF_LIST_DATA_IS_NULL(node, list_s);
+                               if (my_node->pid == node->pid || node->is_for_watch)
+                                       continue;
+                               for (i = 0; i < NUM_OF_STREAM_IO_TYPE; i++) {
+                                       if (!(my_node->status & (i+1)))
+                                               continue;
+                                       if (node->taken_by_id[i].pid == param_s.pid && node->taken_by_id[i].handle_id == param_s.handle_id) {
+                                               /* do callback for resumption */
+                                               if ((ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_ACQUIRE, node, &param_s)))
+                                                       debug_error("Fail to _focus_do_callback for COMMAND ACQUIRE to node[%x], ret[0x%x]", node, ret);
+                                               if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN))
+                                                       need_to_trigger_watch_cb = false;
                                        }
                                }
-                               __clear_focus_pipe(my_node);
-                               g_focus_node_list = g_list_remove(g_focus_node_list, my_node);
-                               list = g_focus_node_list;
                        }
-               } else {
-                       list = list->next;
-                       debug_log("node not found, next list = %p",list);
+                       if (need_to_trigger_watch_cb) {
+                               if ((ret = _mm_sound_mgr_focus_do_watch_callback((focus_type_e)param_s.request_type, FOCUS_COMMAND_RELEASE, my_node, &param_s)))
+                                       debug_error("Fail to _focus_do_watch_callback, ret[0x%x]", ret);
+                       }
+
+                       __clear_focus_pipe(my_node);
+                       g_focus_node_list = g_list_remove(g_focus_node_list, my_node);
+                       list = g_focus_node_list;
                }
        }
 
@@ -1270,7 +1555,7 @@ int MMSoundMgrFocusInit(void)
 
        ret = __mm_sound_mgr_focus_dbus_get_stream_list(&g_stream_list);
        if (ret)
-               debug_error("failed to __mm_sound_mgr_ipc_dbus_get_stream_list()\n");
+               debug_error("failed to __mm_sound_mgr_focus_dbus_get_stream_list()");
 
        debug_fleave();
        return ret;
@@ -1290,4 +1575,3 @@ int MMSoundMgrFocusFini(void)
        debug_fleave();
        return MM_ERROR_NONE;
 }
-