#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); \
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)
{
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] &&
}
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);
}
}
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;
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;
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;
}
}
}
- 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;
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;
}
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;
}
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;
}
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;
}
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;
}
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) {
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) {
}
} 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) {
}
}
- 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;
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;
}
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;
}
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 */
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);
}
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();
/* 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);
}
} 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) {
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);
/* 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;
}
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;
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;
}
}
/* 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;
}
}
}
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;
}
}
}
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 */
/* 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;
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) {
/* 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;
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;
}
}
}
/* 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;
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;
}
/* 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);
}
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);
}
}
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;
}
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;
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(¶m_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, ¶m_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, ¶m_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(¶m_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, ¶m_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, ¶m_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;
}
}
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;
debug_fleave();
return MM_ERROR_NONE;
}
-