Invoke focus watch callback when unregistering node with acquired state 67/127867/1
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 14 Apr 2017 07:16:35 +0000 (16:16 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 2 May 2017 06:09:27 +0000 (15:09 +0900)
Even though there's no node which has lost the focus by this unregistering node,
focus watch callbacks should be called in contrast with focus state callback.
Revise wrong condition of invoking monitor callback.

[Version] 0.10.113
[Profile] Common
[Issue Type] Bug fix

Change-Id: I83fb18081ea94f4e26f7a3aaf158fb0357d7a108
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
focus_server/mm_sound_mgr_focus.c
mm_sound_client.c
packaging/libmm-sound.spec

index e8ae800..e1a5d3c 100644 (file)
@@ -185,7 +185,29 @@ static bool _check_session_node_exist(int pid)
        return false;
 }
 
-static void _invoke_watch_callback(focus_node_t *node, focus_node_t *my_node, focus_type_e focus_type, focus_command_e command, const _mm_sound_mgr_focus_param_t *param)
+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;
@@ -199,8 +221,8 @@ static void _invoke_watch_callback(focus_node_t *node, focus_node_t *my_node, fo
        int fd_FOCUS = -1;
        focus_cb_data cb_data;
 
-       if (!node || !my_node) {
-               debug_error("[CB] invalid argument, node[%p], my_node[%p]\n", node, my_node);
+       if (!node || !stream_type) {
+               debug_error("[CB] invalid argument, node[%p], stream_type[%s]\n", node, stream_type);
                return;
        }
 
@@ -209,7 +231,7 @@ static void _invoke_watch_callback(focus_node_t *node, focus_node_t *my_node, fo
        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.stream_type, stream_type, MAX_STREAM_TYPE_LEN);
        MMSOUND_STRNCPY(cb_data.ext_info, param->ext_info, MM_SOUND_NAME_NUM);
 
        /* Set start time */
@@ -312,6 +334,39 @@ RELEASE:
 }
 
 /* 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;
+
+       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) {
+               if (!(node = (focus_node_t *)list->data))
+                       continue;
+               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);
+       }
+
+       debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
 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;
@@ -329,7 +384,7 @@ static int _mm_sound_mgr_focus_do_monitor_callback(focus_type_e focus_type, focu
                        continue;
                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))
+               if (node == my_node || !(node->pid == my_node->pid && my_node->is_for_session))
                        continue;
                if (!(node->status & focus_type))
                        continue;
@@ -337,7 +392,7 @@ static int _mm_sound_mgr_focus_do_monitor_callback(focus_type_e focus_type, focu
                if (!_check_session_node_exist(node->pid))
                        continue;
 
-               _invoke_watch_callback(node, my_node, focus_type, command, param);
+               _invoke_watch_callback(node, param->stream_type, focus_type, command, param);
        }
 
        debug_fleave();
@@ -367,7 +422,7 @@ static int _mm_sound_mgr_focus_do_watch_callback(focus_type_e focus_type, focus_
                if (node->is_for_monitor)
                        continue;
 
-               _invoke_watch_callback(node, my_node, focus_type, command, param);
+               _invoke_watch_callback(node, my_node->stream_type, focus_type, command, param);
        }
 
        debug_fleave();
@@ -375,7 +430,7 @@ static int _mm_sound_mgr_focus_do_watch_callback(focus_type_e focus_type, focus_
        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;
@@ -432,7 +487,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;
 
@@ -591,7 +646,7 @@ int _mm_sound_mgr_focus_do_callback(focus_command_e command, focus_node_t *victi
        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);
 
@@ -756,7 +811,7 @@ int mm_sound_mgr_focus_destroy_node(const _mm_sound_mgr_focus_param_t *param)
                        if (my_node == node || node->is_for_watch)
                                continue;
                        if (node->pid == my_node->pid && node->is_for_session && node->status) {
-                               debug_error("focus for session for this pid still remains, skip updating victim focus nodes");
+                               debug_warning("another focus node for session of this pid exists, skip invoking callback");
                                need_to_trigger = false;
                                break;
                        }
@@ -764,6 +819,21 @@ int mm_sound_mgr_focus_destroy_node(const _mm_sound_mgr_focus_param_t *param)
        }
 
        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\n");
+                       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) {
                        if (!(node = (focus_node_t *)list->data))
                                continue;
@@ -781,33 +851,23 @@ int mm_sound_mgr_focus_destroy_node(const _mm_sound_mgr_focus_param_t *param)
                                        } else if (my_node->status & (i+1)) {
                                                if (node->is_for_session)
                                                        continue;
-                                               _mm_sound_mgr_focus_param_t *new_param = g_malloc0(sizeof(_mm_sound_mgr_focus_param_t));
-                                               if (!new_param) {
-                                                       debug_warning("Fail to g_malloc0 for new_param, but keep going\n");
-                                                       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->ext_info, my_node->ext_info[i], MM_SOUND_NAME_NUM);
-
                                                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, my_node->stream_type)))
+                                                       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]\n", 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);
-                                                               _mm_sound_mgr_focus_do_watch_callback((focus_type_e)new_param->request_type, FOCUS_COMMAND_RELEASE, my_node, new_param);
                                                        }
-                                                       _mm_sound_mgr_focus_do_monitor_callback((focus_type_e)new_param->request_type, FOCUS_COMMAND_RELEASE, my_node, new_param);
                                                }
-                                               g_free(new_param);
                                        }
                                }
                        }
                }
+               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:
@@ -971,6 +1031,7 @@ 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();
@@ -1021,6 +1082,7 @@ 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) {
                        if (!(node = (focus_node_t *)list->data))
                                continue;
@@ -1031,8 +1093,7 @@ int mm_sound_mgr_focus_request_acquire(const _mm_sound_mgr_focus_param_t *param)
                                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) {
+                                               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]\n", node, ret);
                                                        /* but, keep going */
                                                        ret = MM_ERROR_NONE;
@@ -1040,6 +1101,7 @@ int mm_sound_mgr_focus_request_acquire(const _mm_sound_mgr_focus_param_t *param)
                                                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;
                                        }
                                }
                        }
@@ -1060,7 +1122,9 @@ 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);
-               _mm_sound_mgr_focus_do_monitor_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)) {
@@ -1086,6 +1150,7 @@ 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;
 
@@ -1127,7 +1192,7 @@ int mm_sound_mgr_focus_request_release(const _mm_sound_mgr_focus_param_t *param)
                        if (node == my_node || node->is_for_watch)
                                continue;
                        if (node->pid == my_node->pid && node->is_for_session && node->status) {
-                               debug_error("focus for session for this pid is active, skip callbacks");
+                               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;
@@ -1138,6 +1203,7 @@ 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) {
                        if (!(node = (focus_node_t *)list->data))
                                continue;
@@ -1147,13 +1213,12 @@ int mm_sound_mgr_focus_request_release(const _mm_sound_mgr_focus_param_t *param)
                                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) {
+                                               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]\n", 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;
                                        }
                                }
                        }
@@ -1171,7 +1236,8 @@ 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);
-       _mm_sound_mgr_focus_do_monitor_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 ();
@@ -1333,6 +1399,7 @@ int mm_sound_mgr_focus_emergent_exit(const _mm_sound_mgr_focus_param_t *param)
                        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) {
                                if (!(node = (focus_node_t *)list_s->data))
                                        continue;
@@ -1343,7 +1410,7 @@ int mm_sound_mgr_focus_emergent_exit(const _mm_sound_mgr_focus_param_t *param)
                                                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, my_node->stream_type)))
+                                               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]\n", node, ret);
                                                if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN))
                                                        need_to_trigger_watch_cb = false;
@@ -1354,8 +1421,6 @@ int mm_sound_mgr_focus_emergent_exit(const _mm_sound_mgr_focus_param_t *param)
                                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]\n", ret);
                        }
-                       if ((ret = _mm_sound_mgr_focus_do_monitor_callback((focus_type_e)param_s.request_type, FOCUS_COMMAND_RELEASE, my_node, &param_s)))
-                               debug_error("Fail to _focus_do_monitor_callback, ret[0x%x]\n", ret);
 
                        __clear_focus_pipe(my_node);
                        g_focus_node_list = g_list_remove(g_focus_node_list, my_node);
index bceaecf..57afc72 100644 (file)
@@ -1106,8 +1106,8 @@ static void _session_interrupted_cb(int id, mm_sound_focus_type_e focus_type, mm
        }
 
        debug_msg("  >>> invoking session interrupt callback(%p)", g_focus_session_interrupt_info.user_cb);
-       if (state == FOCUS_IS_ACQUIRED)
-               (g_focus_session_interrupt_info.user_cb)(state, reason_for_change, g_focus_session_interrupt_info.user_data);
+       if (state == FOCUS_IS_RELEASED)
+               (g_focus_session_interrupt_info.user_cb)(FOCUS_IS_ACQUIRED, reason_for_change, g_focus_session_interrupt_info.user_data);
        else {
                debug_msg("INTERRUPTED COMPLETED case, append it to idle");
                g_idle_add((GSourceFunc)_interrupted_completed, strdup(reason_for_change));
index d3b998f..a4aad36 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-sound
 Summary:    MMSound Package contains client lib and sound_server binary
-Version:    0.10.112
+Version:    0.10.113
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0