diff options
author | Kibum Kim <kb0929.kim@samsung.com> | 2012-02-27 21:15:48 +0900 |
---|---|---|
committer | Kibum Kim <kb0929.kim@samsung.com> | 2012-02-27 21:15:48 +0900 |
commit | 10c786e725207327fb35035100b391d073da6aeb (patch) | |
tree | 27e35f47dfbe9651647e8df83be258ceff8796df /src | |
download | audio-session-manager-10c786e725207327fb35035100b391d073da6aeb.tar.gz audio-session-manager-10c786e725207327fb35035100b391d073da6aeb.tar.bz2 audio-session-manager-10c786e725207327fb35035100b391d073da6aeb.zip |
tizen beta release
Diffstat (limited to 'src')
-rw-r--r-- | src/audio-session-mgr-server.c | 1582 | ||||
-rw-r--r-- | src/audio-session-mgr.c | 1252 |
2 files changed, 2834 insertions, 0 deletions
diff --git a/src/audio-session-mgr-server.c b/src/audio-session-mgr-server.c new file mode 100644 index 0000000..f7bbd1b --- /dev/null +++ b/src/audio-session-mgr-server.c @@ -0,0 +1,1582 @@ +/* + * audio-session-manager + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Seungbae Shin <seungbae.shin@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/ipc.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/msg.h> +#include <glib.h> +#include <glib/gprintf.h> +#include <poll.h> + +#include <vconf.h> +#include <audio-session-manager.h> +#include <asm-log.h> +#include <string.h> +#include <errno.h> + +#include <sysman.h> + +#ifdef USE_SECURITY +#include <security-server.h> +#endif + +#include <avsys-audio.h> + +#define HIBERNATION_CHECK_KEY "memory/hibernation/audio_ready" +#define HIBERNATION_READY 1 +#define USE_SYSTEM_SERVER_PROCESS_MONITORING + +#define SUPPORT_GCF /* currently in use */ + +static const ASM_sound_cases_t ASM_sound_case[ASM_PRIORITY_MATRIX_MIN+1][ASM_PRIORITY_MATRIX_MIN+1] = +{ + /* SP SC SS SO SA, EP EC ES EO EA, N C SF EF EU, A VC M */ + { 8, 8, 8, 8, 8, 6, 6, 6, 6, 6, 8, 8, 8, 6, 6, 6, 6, 8 }, /* 00 Shared MMPlayer */ + { 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 8, 5, 8, 5, 8, 5, 5, 8 }, /* 01 Shared MMCamcorder */ + { 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 8, 5, 8, 5, 6, 5, 5, 8 }, /* 02 Shared MMSound */ + { 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 8, 5, 8, 5, 6, 5, 5, 8 }, /* 03 Shared OpenAL */ + { 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 8, 5, 8, 5, 8, 5, 5, 8 }, /* 04 Shared AVsystem */ + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 6, 6, 6, 6, 6, 8 }, /* 05 Exclusive MMPlayer */ + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 5, 5, 8, 5, 5 ,8 }, /* 06 Exclusive MMCamcorder */ + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 5, 5, 6, 5, 5, 8 }, /* 07 Exclusive MMSound */ + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 5, 5, 6, 5, 5, 8 }, /* 08 Exclusive OpenAL */ + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 5, 5, 8, 5, 5, 8 }, /* 09 Exclusive AVsystem */ + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 8, 8, 8, 5, 5, 8 }, /* 10 Notify */ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 0, 1, 1, 8, 8, 1, 8 }, /* 11 Call */ + { 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 8, 5, 5, 5, 8, 5, 5, 8 }, /* 12 Shared FMradio */ + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 5, 5, 8, 5, 5, 8 }, /* 13 Exclusive FMradio */ + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, /* 14 Earjack Unplug */ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 5, 1, 1, 8, 8, 5, 8 }, /* 15 Alarm */ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 8, 8, 0, 8 }, /* 16 Video Call */ + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, /* 17 Monitor */ +}; + +typedef struct _list +{ + long int instance_id; + int sound_handle; + ASM_sound_events_t sound_event; + ASM_sound_states_t sound_state; + ASM_resume_states_t need_resume; + ASM_resource_t mm_resource; + avsys_audio_playing_devcie_t device_when_interrupted; + unsigned short monitor_active; + unsigned short monitor_dirty; + struct _list *next; +} asm_instance_list_t; + +asm_instance_list_t *head_list, *tail_list; + +int asm_snd_msgid; +int asm_rcv_msgid; +int asm_cb_msgid; +ASM_msg_lib_to_asm_t asm_rcv_msg; +ASM_msg_asm_to_lib_t asm_snd_msg; +ASM_msg_asm_to_cb_t asm_cb_msg; + +bool asm_is_send_msg_to_cb = false; + +#ifdef SUPPORT_GCF +#define GCF_DEFAULT 0 +int is_gcf = GCF_DEFAULT; +#endif + +unsigned int g_sound_status_pause = 0; +unsigned int g_sound_status_playing = 0; + +#define SERVER_HANDLE_MAX_COUNT 256 + +static const char* ASM_sound_events_str[] = +{ + "SHARE_MMPLAYER", + "SHARE_MMCAMCORDER", + "SHARE_MMSOUND", + "SHARE_OPENAL", + "SHARE_AVSYSTEM", + "EXCLUSIVE_MMPLAYER", + "EXCLUSIVE_MMCAMCORDER", + "EXCLUSIVE_MMSOUND", + "EXCLUSIVE_OPENAL", + "EXCLUSIVE_AVSYSTEM", + "NOTIFY", + "CALL", + "SHARE_FMRADIO", + "EXCLUSIVE_FMRADIO", + "EARJACK_UNPLUG", + "ALARM", + "VIDEOCALL", + "MONITOR" +}; + +static const char* ASM_sound_state_str[] = +{ + "STATE_NONE", + "STATE_PLAYING", + "STATE_WAITING", + "STATE_STOP", + "STATE_PAUSE", + "STATE_PAUSE_BY_APP", + "STATE_ALTER_PLAYING" +}; + + +static const char* ASM_sound_request_str[] = +{ + "REQUEST_REGISTER", + "REQUEST_UNREGISTER", + "REQUEST_GETSTATE", + "REQUEST_GETMYSTATE", + "REQUEST_SETSTATE", + "REQUEST_EMEGENT_EXIT", + "REQUEST_DUMP" +}; + + +static const char* ASM_sound_cases_str[] = +{ + "CASE_NONE", + "CASE_1PLAY_2STOP", + "CASE_1PLAY_2ALTER_PLAY", + "CASE_1PLAY_2WAIT", + "CASE_1ALTER_PLAY_2PLAY", + "CASE_1STOP_2PLAY", + "CASE_1PAUSE_2PLAY", + "CASE_1VIRTUAL_2PLAY", + "CASE_1PLAY_2PLAY_MIX" +}; + +static const char* ASM_sound_resume_str[] = +{ + "NO-RESUME", + "RESUME" +}; + + +static const char* ASM_sound_command_str[] = +{ + "CMD_NONE", + "CMD_WAIT", + "CMD_PLAY", + "CMD_STOP", + "CMD_PAUSE", + "CMD_RESUME", +}; + +#define ASM_SND_MSG_SET(asm_snd_msg, x_alloc_handle, x_cmd_handle, x_result_sound_command, x_result_sound_state) \ +do { \ + asm_snd_msg.data.alloc_handle = x_alloc_handle; \ + asm_snd_msg.data.cmd_handle = x_cmd_handle; \ + asm_snd_msg.data.result_sound_command = x_result_sound_command; \ + asm_snd_msg.data.result_sound_state = x_result_sound_state; \ +} while (0) + +void selectSleep(int secs) +{ + struct timeval timeout; + timeout.tv_sec = (secs < 1 || secs > 10) ? 3 : secs; + timeout.tv_usec = 0; + select(0, NULL, NULL, NULL, &timeout); + return; +} + + +gboolean __find_clean_monitor_handle(int instance_id, int *handle) +{ + asm_instance_list_t *temp_list = head_list; + int lhandle = -1; + + while (temp_list->next != tail_list) { + if (temp_list->instance_id == instance_id && temp_list->sound_event == ASM_EVENT_MONITOR) { + if (temp_list->monitor_dirty == 0) { + lhandle = temp_list->sound_handle; + } + break; + } + temp_list = temp_list->next; + } + if (lhandle == -1) { + return FALSE; + } else { + *handle = lhandle; + return TRUE; + } +} + +void __update_monitor_active(long int instance_id) +{ + asm_instance_list_t *temp_list = head_list; + asm_instance_list_t *monitor_list = NULL; + unsigned short active = 0; + asm_info("[ASM_Server] %s\n",__func__); + + while (temp_list->next != tail_list) { + if (temp_list->instance_id == instance_id && temp_list->sound_event == ASM_EVENT_MONITOR) { + /* backup monitor pointer */ + monitor_list = temp_list; + break; + } + temp_list = temp_list->next; + } + if (NULL == monitor_list) { + asm_warning("[ASM_Server] %s : No monitor instance for %d\n",__func__, instance_id); + return; + } + + temp_list = head_list; + while (temp_list->next != tail_list) { + if (temp_list->instance_id == instance_id && temp_list->sound_event != ASM_EVENT_MONITOR) { + if (ASM_STATE_PLAYING == temp_list->sound_state) { + active = 1; + break; + } + } + temp_list = temp_list->next; + } + + monitor_list->monitor_active = active; +} + +void __set_all_monitor_clean() +{ + asm_instance_list_t *temp_list = head_list; + + while (temp_list->next != tail_list) { + if (temp_list->sound_event == ASM_EVENT_MONITOR) { + temp_list->monitor_dirty = 0; + } + temp_list = temp_list->next; + } +} + +void __set_monitor_dirty(long int instance_id) +{ + asm_instance_list_t *temp_list = head_list; + + while (temp_list->next != tail_list) { + if (temp_list->instance_id == instance_id && temp_list->sound_event == ASM_EVENT_MONITOR) { + temp_list->monitor_dirty = 1; + break; + } + temp_list = temp_list->next; + } +} + +/* callback without retcb */ +void __do_callback_wo_retcb(int instance_id,int handle,int command) +{ + int fd_ASM = 0, cur_handle = 0; + char *filename = g_strdup_printf("/tmp/ASM.%d.%d", instance_id, handle); + + if ((fd_ASM = open(filename,O_WRONLY|O_NONBLOCK)) < 0) { + asm_info("[ASM_Server][CallCB] %s open error",filename); + g_free(filename); + return; + } + cur_handle = (unsigned int)(handle |(command << 4)); + if (write(fd_ASM, (void *)&cur_handle, sizeof(cur_handle)) < 0) { + asm_info("[ASM_Server][CallCB] %s write error",filename); + g_free(filename); + return; + } + close(fd_ASM); + g_free(filename); + selectSleep(2); /* if return immediately bad sound occur */ +} + + +int __do_callback(int instance_id,int handle,int command, ASM_event_sources_t event_src) +{ + char *filename = NULL; + char *filename2 = NULL; + struct timeval time; + int starttime = 0; + int endtime = 0; + int fd=0,nread = 0; + int fd_ASM = 0, cur_handle = 0; + int buf = 0; + struct pollfd pfd; + int pret = 0; + int pollingTimeout = 7000; + + asm_info("[ASM_Server] __do_callback for pid(%d) handle(%d)\n", instance_id, handle); + + /* Set start time */ + gettimeofday(&time, NULL); + starttime = time.tv_sec * 1000000 + time.tv_usec; + + /************************************** + * + * Open callback cmd pipe + * + **************************************/ + filename = g_strdup_printf("/tmp/ASM.%d.%d", instance_id, handle); + if ((fd_ASM = open(filename, O_WRONLY|O_NONBLOCK)) < 0) { + asm_error("[ASM_Server][CallCB] %s open error\n", filename); + goto fail; + } + + /****************************************** + * + * Open callback result pipe + * before writing callback cmd to pipe + * + ******************************************/ + filename2 = g_strdup_printf("/tmp/ASM.%d.%dr", instance_id, handle); + if ((fd=open(filename2,O_RDONLY|O_NONBLOCK))== -1) { + char str_error[256]; + strerror_r (errno, str_error, sizeof(str_error)); + asm_error("[ASM_Server][RETCB] Fail to open fifo (%s)\n", str_error); + goto fail; + } + asm_info("[ASM_Server] open return cb %s\n", filename2); + + + /******************************************* + * Write Callback msg + *******************************************/ + cur_handle = (unsigned int)((0x0000ffff & handle) |(command << 16) | (event_src << 24)); + if (write(fd_ASM, (void *)&cur_handle, sizeof(cur_handle)) < 0) { + asm_error("[ASM_Server][CallCB] %s write error\n", filename); + goto fail; + } + /************************************** + * + * Close callback cmd pipe + * + **************************************/ + close(fd_ASM); + fd_ASM = -1; + g_free(filename); + filename = NULL; + + pfd.fd = fd; + pfd.events = POLLIN; + + asm_instance_list_t *temp_list = head_list; + + + /********************************************* + * + * Wait callback result msg + * + ********************************************/ + asm_critical("[ASM_Server][RETCB]wait callback(tid=%d, handle=%d, cmd=%d, timeout=%d)\n", instance_id, handle, command, pollingTimeout); + pret = poll(&pfd, 1, pollingTimeout); //timeout 7sec + if (pret < 0) { + asm_error("[ASM_Server][RETCB]poll failed (%d)\n", pret); + goto fail; + } + if (pfd.revents & POLLIN) { + nread=read(fd, (void *)&buf, sizeof(buf)); + } + g_free(filename2); + filename2 = NULL; + + /* Calculate endtime and display*/ + gettimeofday(&time, NULL); + endtime = time.tv_sec * 1000000 + time.tv_usec; + asm_critical("[ASM_Server][RETCB] ASM_CB_END cbtimelab=%3.3f(second), timeout=%d(milli second) (reciever=%d)\n", ((endtime-starttime)/1000000.), pollingTimeout, instance_id); + + /************************************** + * + * Close callback result pipe + * + **************************************/ + close(fd); + fd = -1; + asm_info("[ASM_Server][RETCB] Return value 0x%x\n", buf); + return buf; + +fail: + if (filename) { + g_free (filename); + filename = NULL; + } + if (filename2) { + g_free (filename2); + filename2 = NULL; + } + if (fd_ASM != -1) { + close(fd_ASM); + fd_ASM = -1; + } + if (fd != -1) { + close (fd); + fd = -1; + } + + return -1; +} + +gboolean __isPlayingNow() +{ + asm_instance_list_t *temp_list = head_list; + while (temp_list->next != tail_list) { + if (temp_list->sound_state == ASM_STATE_PLAYING ) { + return TRUE; + } + + temp_list = temp_list->next; + } + return FALSE; +} + +gboolean __isItPlayingNow(int instance_id, int handle) +{ + asm_instance_list_t *temp_list = head_list; + while (temp_list->next != tail_list) { + if (temp_list->instance_id == instance_id && temp_list->sound_handle == handle) { + if (temp_list->sound_state == ASM_STATE_PLAYING) { + return TRUE; + } + } + + temp_list = temp_list->next; + } + return FALSE; +} + +void __temp_print_list(char * msg) +{ + asm_instance_list_t *temp_list = head_list; + int i = 0; + + if (NULL != msg) { + asm_warning("[ASM_Server] %s\n", msg); + } + while (temp_list->next != tail_list) { + asm_info("[ASM_Server] List[%02d] ( %5ld, %2d, %-20s, %-20s, %9s, 0x%04x)\n", i, temp_list->instance_id, temp_list->sound_handle, + ASM_sound_events_str[temp_list->sound_event], + ASM_sound_state_str[temp_list->sound_state], + ASM_sound_resume_str[temp_list->need_resume], + temp_list->mm_resource); + temp_list = temp_list->next; + i++; + } +} + +void updatePhoneStatus() +{ + asm_instance_list_t *temp_list = head_list; + int i = 0, error = 0; + + g_sound_status_pause = 0; + g_sound_status_playing = 0; + + while (temp_list->next != tail_list) { + if (temp_list->sound_state == ASM_STATE_PLAYING) { + if (temp_list->sound_event >= ASM_EVENT_SHARE_MMPLAYER && temp_list->sound_event < ASM_EVENT_MAX) { + g_sound_status_playing |= ASM_sound_type[(temp_list->sound_event) + 1].sound_status; + } + } else if (temp_list->sound_state == ASM_STATE_PAUSE ) { + if (temp_list->sound_event >= ASM_EVENT_SHARE_MMPLAYER && temp_list->sound_event < ASM_EVENT_MAX) { + g_sound_status_pause |= ASM_sound_type[(temp_list->sound_event) + 1].sound_status; + } + } + temp_list = temp_list->next; + } + + if (vconf_set_int(SOUND_STATUS_KEY, g_sound_status_playing)) { + asm_info("[ASM_Server[Error = %d][1st try] phonestatus_set \n", error); + if (vconf_set_int(SOUND_STATUS_KEY, g_sound_status_playing)) { + asm_critical("[ASM_Server][Error = %d][2nd try] phonestatus_set \n", error); + } + } + + asm_info("[ASM_Server] soundstatus set to (0x%08x)\n", g_sound_status_playing); +} + + +void __asm_register_list(long int instance_id, int handle, ASM_sound_events_t sound_event, ASM_sound_states_t sound_state, ASM_resource_t mm_resource) +{ + asm_instance_list_t *temp_list; + temp_list = (asm_instance_list_t *)malloc(sizeof(asm_instance_list_t)); + temp_list->instance_id = instance_id; + temp_list->sound_handle = handle; + temp_list->sound_event = sound_event; + temp_list->sound_state = sound_state; + temp_list->need_resume = 0; + temp_list->mm_resource = mm_resource; + temp_list->monitor_active = 0; + temp_list->monitor_dirty = 0; + temp_list->device_when_interrupted = AVSYS_AUDIO_ROUTE_DEVICE_UNKNOWN; + temp_list->next = head_list; + head_list = temp_list; + + __temp_print_list("Register List"); + updatePhoneStatus(); +} + +int __asm_unregister_list(int handle) +{ + asm_instance_list_t *temp_list = head_list; + asm_instance_list_t *temp_list2 = head_list; + int instance_id = -1; + + asm_info("[ASM_Server] __asm_unregister_list \n"); + + while (temp_list->next != tail_list) { + if (temp_list->sound_handle == handle) { + instance_id = temp_list->instance_id; + if (temp_list == head_list) + head_list = temp_list->next; + else + temp_list2->next = temp_list->next; + free(temp_list); + break; + } + temp_list2 = temp_list; + temp_list = temp_list->next; + } + + __temp_print_list("Unregister List for handle"); + updatePhoneStatus(); + return instance_id; +} + + +/* ------------------------- + * if PID exist return true, else return false + */ +gboolean isPIDExist(int pid) +{ + if (pid > 999999 || pid < 2) + return FALSE; + gchar *tmp = g_malloc0(25); + g_sprintf(tmp, "/proc/%d", pid); + if (access(tmp, R_OK)==0) { + g_free(tmp); + return TRUE; + } + g_free(tmp); + return FALSE; +} + + +/* ------------------------- + * + */ +void __check_dead_process() +{ + asm_instance_list_t *temp_list = head_list; + asm_instance_list_t *temp_list2 = head_list; + while (temp_list->next != tail_list) { + if (!isPIDExist(temp_list->instance_id)) { + asm_critical_r("[ASM_Server] PID(%ld) not exist! -> ASM_Server resource of pid(%ld) will be cleared \n", temp_list->instance_id, temp_list->instance_id); + + if (temp_list == head_list) { + head_list = temp_list->next; + } + temp_list2->next = temp_list->next; + free(temp_list); + } else { + temp_list2 = temp_list; + } + temp_list = temp_list2->next; + } + updatePhoneStatus(); +} + + + + +void emergent_exit(int exit_pid) +{ + asm_instance_list_t *temp_list = head_list; + int handle = -1; + int instance_id = -1; + + while (temp_list->next != tail_list) { + if (temp_list->instance_id == exit_pid) { + handle = temp_list->sound_handle; + + instance_id = __asm_unregister_list(handle); + + if (instance_id != -1) { + char str_error[256]; + char* filename = g_strdup_printf("/tmp/ASM.%d.%d", instance_id, handle); + char* filename2 = g_strdup_printf("/tmp/ASM.%d.%dr", instance_id, handle); + if (!remove(filename)) { + asm_info("[ASM_Server] remove %s success\n", filename); + } else { + strerror_r (errno, str_error, sizeof (str_error)); + asm_error("[ASM_Server] remove %s failed with %s\n", filename, str_error); + } + + if (!remove(filename2)) { + asm_info("[ASM_Server] remove %s success\n", filename2); + } else { + strerror_r (errno, str_error, sizeof (str_error)); + asm_error("[ASM_Server] remove %s failed with %s\n", filename2, str_error); + } + + g_free(filename); + g_free(filename2); + } + temp_list = head_list; + } else { + temp_list = temp_list->next; + } + } + + asm_info("[ASM_Server][EMERGENT_EXIT] complete\n"); + return; +} + + +int ___reorder_state(ASM_sound_states_t input) +{ + int res = 0; + + switch (input) { + case ASM_STATE_IGNORE: + case ASM_STATE_NONE: + res = 0; + break; + case ASM_STATE_WAITING: + case ASM_STATE_STOP: + res = 1; + break; + case ASM_STATE_PAUSE: + case ASM_STATE_PAUSE_BY_APP: + res = 2; + break; + case ASM_STATE_PLAYING: + res = 3; + break; + } + return res; +} + +ASM_sound_states_t __asm_find_process_status(int pid) +{ + asm_instance_list_t *temp_list = head_list; + ASM_sound_states_t result_state = ASM_STATE_NONE; + + asm_info("[ASM_Server] __asm_find_process_status for pid %d\n", pid); + + while (temp_list->next != tail_list) { + if (temp_list->instance_id == pid) { + if ( ___reorder_state(temp_list->sound_state) >= ___reorder_state(result_state)) { + result_state = temp_list->sound_state; + } + } + temp_list = temp_list->next; + } + + return result_state; +} + +ASM_sound_states_t __asm_find_list(ASM_requests_t request_id, int handle) +{ + asm_instance_list_t *temp_list = head_list; + + asm_info("[ASM_Server] __asm_find_list\n"); + + while (temp_list->next != tail_list) { + if ((request_id == ASM_REQUEST_GETSTATE && temp_list->sound_handle == handle)) { + return temp_list->sound_state; + } else { + temp_list = temp_list->next; + } + } + + return ASM_STATE_NONE; +} + +void __asm_change_state_list(long int instance_id, int handle, ASM_sound_states_t sound_state, ASM_resource_t mm_resource) +{ + asm_instance_list_t *temp_list = head_list; + int monitor_handle = -1; + asm_info("[ASM_Server] __asm_change_state_list\n"); + if (sound_state == ASM_STATE_IGNORE) { + asm_info("[ASM_Server] skip update state list %ld-%d\n", instance_id, handle); + return; + } + + while (temp_list->next != tail_list) { + if (temp_list->instance_id == instance_id && temp_list->sound_handle == handle) { + temp_list->sound_state = sound_state; + temp_list->mm_resource = mm_resource; + break; + } + temp_list = temp_list->next; + } + __update_monitor_active(instance_id); + updatePhoneStatus(); +} + +void __asm_change_need_resume_list(long int instance_id, int handle, ASM_resume_states_t need_resume) +{ + asm_instance_list_t *temp_list = head_list; + asm_info("[ASM_Server] __asm_change_need_resume_list\n"); + while (temp_list->next != tail_list) { + if (temp_list->instance_id == instance_id && temp_list->sound_handle == handle) { + temp_list->need_resume = need_resume; + + if (need_resume == ASM_NEED_RESUME) { + avsys_audio_playing_devcie_t dev = AVSYS_AUDIO_ROUTE_DEVICE_UNKNOWN; + if (AVSYS_SUCCESS(avsys_audio_get_playing_device_info(&dev))) { + temp_list->device_when_interrupted = dev; + } + } + break; + } + temp_list = temp_list->next; + } +} + + +void __asm_create_message_queue() +{ + asm_rcv_msgid = msgget((key_t)2014, 0666 | IPC_CREAT); + asm_snd_msgid = msgget((key_t)4102, 0666 | IPC_CREAT); + asm_cb_msgid = msgget((key_t)4103, 0666 | IPC_CREAT); + + if (asm_snd_msgid == -1 || asm_rcv_msgid == -1 || asm_cb_msgid == -1) { + asm_critical("[ASM_Server] msgget failed with error: \n"); + exit(EXIT_FAILURE); + } +} + +void __asm_snd_message() +{ + if (msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0) == -1) { + asm_critical("[ASM_Server] msgsnd failed with error %d\n", errno); + exit(EXIT_FAILURE); + } +} + +void __asm_cb_message() +{ + if (msgsnd(asm_cb_msgid, (void *)&asm_cb_msg, sizeof(asm_cb_msg.data), 0) == -1) { + asm_critical_r("[ASM_Server] msgsnd(Callback msg) failed with error %d\n", errno); + exit(EXIT_FAILURE); + } +} + +void __asm_rcv_message() +{ + if (msgrcv(asm_rcv_msgid, (void *)&asm_rcv_msg, sizeof(asm_rcv_msg.data), 0, 0) == -1) { + asm_critical_r("[ASM_Server] msgrcv failed with error %d\n", errno); + exit(EXIT_FAILURE); + } +} + +void __asm_get_empty_handle(long int instance_id, int *handle) +{ + asm_instance_list_t *temp_list = head_list; + unsigned int i = 0, find_empty = 0, j = 0; + char handle_info[SERVER_HANDLE_MAX_COUNT]; + + asm_info("[ASM_Server] __asm_make_handle for %ld\n", instance_id); + __temp_print_list("current list before get new handle"); + + memset(handle_info, 0, sizeof(char) * SERVER_HANDLE_MAX_COUNT); + + while (temp_list->next != tail_list) { + handle_info[temp_list->sound_handle] = 1; + temp_list = temp_list->next; + } + + for (i = 0; i < ASM_SERVER_HANDLE_MAX; i++) { + if (handle_info[i] == 0) { + find_empty = 1; + break; + } + } + if (find_empty && (i != ASM_SERVER_HANDLE_MAX)) { + asm_error_r("[ASM_Server] New handle for %ld is %d\n", instance_id, i); + *handle = i; + } else { + asm_error_r("[ASM_Server] Handle is full for pid %ld\n", instance_id); + *handle = -1; + } + +} + +void __print_resource(unsigned short resource_status) +{ + if (resource_status == ASM_RESOURCE_NONE) + asm_info("[ASM_Server] resource NONE\n"); + if (resource_status | ASM_RESOURCE_CAMERA) + asm_info("[ASM_Server] resource CAMERA\n"); + if (resource_status | ASM_RESOURCE_VIDEO_OVERLAY) + asm_info("[ASM_Server] resource VIDEO OVERLAY\n"); + if (resource_status | ASM_RESOURCE_HW_ENCORDER) + asm_info("[ASM_Server] resource HW ENCORDER\n"); + if (resource_status | ASM_RESOURCE_HW_DECORDER) + asm_info("[ASM_Server] resource HW DECORDER\n"); + if (resource_status | ASM_RESOURCE_RADIO_TUNNER) + asm_info("[ASM_Server] resource RADIO TUNNER\n"); + if (resource_status | ASM_RESOURCE_TV_TUNNER) + asm_info("[ASM_Server] resource TV TUNNER\n"); +} + +void __asm_compare_priority_matrix(long int instance_id, int handle, ASM_requests_t request_id, + ASM_sound_events_t sound_event,ASM_sound_states_t sound_state, ASM_resource_t mm_resource) +{ + int no_conflict_flag = 0; + + /* If nobody is playing now, this means no conflict */ + if (ASM_STATUS_NONE == g_sound_status_playing) { + asm_info("[ASM_Server] __asm_compare_priority_matrix : No conflict ( No existing Sound )\n"); + + ASM_SND_MSG_SET(asm_snd_msg, handle, -1, ASM_COMMAND_NONE, sound_state); + + no_conflict_flag = 1; + } else { /* Somebody is playing */ + asm_instance_list_t *temp_list = head_list; + int updatedflag = 0; + int cb_res = 0; + int update_state = ASM_STATE_NONE; + + while (temp_list->next != tail_list) { + /* Find who's playing now */ + if (temp_list->sound_state == ASM_STATE_PLAYING) { + /* Found it */ + ASM_sound_states_t current_play_state = temp_list->sound_state; + ASM_sound_events_t current_play_sound_event = temp_list->sound_event; + long int current_play_instance_id = temp_list->instance_id; + int current_play_handle = temp_list->sound_handle; + ASM_resource_t current_using_resource = temp_list->mm_resource; + + if ((current_play_instance_id == instance_id) && (current_play_handle == handle)) { + asm_warning("[ASM_Server] This is my handle. skip %d %d\n", instance_id, handle); + temp_list = temp_list->next; + continue; + } + + /* Request is PLAYING */ + if (sound_state == ASM_STATE_PLAYING) { + /* Determine sound policy */ + ASM_sound_cases_t sound_case = ASM_sound_case[current_play_sound_event][sound_event]; + +#ifdef SUPPORT_GCF + /* GCF case is exception case */ + /* NOTE : GCF exception case only */ + if ((is_gcf) && (sound_case != ASM_CASE_1PLAY_2PLAY_MIX)) { + sound_case = ASM_CASE_1PLAY_2PLAY_MIX;; + } +#endif + + asm_critical("[ASM_Server] Conflict policy[%x][%x]: %s\n", current_play_sound_event,sound_event,ASM_sound_cases_str[sound_case]); + switch (sound_case) { + case ASM_CASE_1PLAY_2STOP: + { + if (current_play_instance_id == instance_id) { + /* PID is policy group.*/ + asm_info("[ASM_Server] Do not send Stop callback in same pid %ld\n", instance_id); + } else { + ASM_SND_MSG_SET(asm_snd_msg, handle, handle, ASM_COMMAND_STOP, sound_state); + temp_list = tail_list; /* skip all remain list */ + break; + } + + /* Prepare msg to send */ + ASM_SND_MSG_SET(asm_snd_msg, handle, handle, ASM_COMMAND_PLAY, sound_state); + + if (!updatedflag) { + if (request_id == ASM_REQUEST_REGISTER){ + __asm_register_list(instance_id, handle, sound_event, sound_state, mm_resource); + } else { + __asm_change_state_list(instance_id, handle, sound_state, mm_resource); + } + updatedflag = 1; + } + break; + } + + case ASM_CASE_1STOP_2PLAY: + { + if (current_play_instance_id == instance_id) { + /* PID is policy group. */ + asm_info("[ASM_Server] Do not send Stop callback in same pid %ld\n", instance_id); + } else { + ASM_event_sources_t event_src; + unsigned short resource_status = current_using_resource & mm_resource; + + /* Determine root cause of conflict */ + if (resource_status != ASM_RESOURCE_NONE) { + event_src = ASM_EVENT_SOURCE_RESOURCE_CONFLICT; + } else { + switch (sound_event) { + case ASM_EVENT_CALL: + case ASM_EVENT_VIDEOCALL: + event_src = ASM_EVENT_SOURCE_CALL_START; + break; + + case ASM_EVENT_EARJACK_UNPLUG: + event_src = ASM_EVENT_SOURCE_EARJACK_UNPLUG; + break; + + case ASM_EVENT_ALARM: + event_src = ASM_EVENT_SOURCE_ALARM_START; + break; + + default: + event_src = ASM_EVENT_SOURCE_OTHER_APP; + break; + } + } + + /* Execute callback function for monitor handle */ + int monitor_handle = -1; + if (__find_clean_monitor_handle(current_play_instance_id, &monitor_handle)) { + cb_res = __do_callback(current_play_instance_id, monitor_handle, ASM_COMMAND_STOP, event_src); + asm_warning("[ASM_Server] send stop callback for monitor handle of pid %d\n", current_play_instance_id); + if (cb_res != ASM_CB_RES_NONE && cb_res != ASM_CB_RES_STOP) { + asm_error_r("[ASM_Server] oops! not suspected callback result %d\n", cb_res); + } + __set_monitor_dirty(current_play_instance_id); + + /* If current is playing and input event is CALL/VIDEOCALL/ALARM, set to need resume */ + if ((sound_event == ASM_EVENT_CALL || sound_event == ASM_EVENT_VIDEOCALL || sound_event == ASM_EVENT_ALARM) + && (current_play_state == ASM_STATE_PLAYING)) { + __asm_change_need_resume_list(current_play_instance_id, monitor_handle, ASM_NEED_RESUME); + } + } + + /* Execute callback function for worker handle */ + cb_res = __do_callback(current_play_instance_id,current_play_handle,ASM_COMMAND_STOP, event_src); + if (cb_res != ASM_CB_RES_NONE && cb_res != ASM_CB_RES_STOP) + asm_error_r("[ASM_Server] oops! not suspected result %d\n", cb_res); + asm_warning("[ASM_Server] __asm_compare_priority_matrix(1STOP_2PLAY) : __do_callback Complete : TID=%ld, handle=%d", + current_play_instance_id,current_play_handle ); + + /* If current is playing and input event is CALL/VIDEOCALL/ALARM, set to need resume */ + if ((sound_event == ASM_EVENT_CALL || sound_event == ASM_EVENT_VIDEOCALL || sound_event == ASM_EVENT_ALARM) + && (current_play_state == ASM_STATE_PLAYING)) { + __asm_change_need_resume_list(current_play_instance_id, current_play_handle, ASM_NEED_RESUME); + } + + /* Set state to NONE */ + __asm_change_state_list(current_play_instance_id, current_play_handle, ASM_STATE_NONE, ASM_RESOURCE_NONE); + } + + /* Prepare msg to send */ + ASM_SND_MSG_SET(asm_snd_msg, handle, handle, ASM_COMMAND_PLAY, sound_state); + + if (!updatedflag) { + if (request_id == ASM_REQUEST_REGISTER) { + __asm_register_list(instance_id, handle, sound_event, sound_state, mm_resource); + } else { + __asm_change_state_list(instance_id, handle, sound_state, mm_resource); + } + updatedflag = 1; + } + break; + } + + case ASM_CASE_1PAUSE_2PLAY: + { + ASM_resource_t update_resource = current_using_resource; + if (current_play_instance_id == instance_id) { + asm_info("[ASM_Server] Do not send Pause callback in same pid %ld\n", instance_id); + } else { + ASM_event_sources_t event_src; + ASM_sound_commands_t command; + + unsigned short resource_status = current_using_resource & mm_resource; + if (resource_status != ASM_RESOURCE_NONE) { + asm_info("[ASM_Server] resource conflict found 0x%x\n", resource_status); + event_src = ASM_EVENT_SOURCE_RESOURCE_CONFLICT; + command = ASM_COMMAND_STOP; + } else { + switch (sound_event) { + case ASM_EVENT_CALL: + case ASM_EVENT_VIDEOCALL: + event_src = ASM_EVENT_SOURCE_CALL_START; + break; + + case ASM_EVENT_EARJACK_UNPLUG: + event_src = ASM_EVENT_SOURCE_EARJACK_UNPLUG; + break; + + case ASM_EVENT_ALARM: + event_src = ASM_EVENT_SOURCE_ALARM_START; + break; + + case ASM_EVENT_SHARE_MMPLAYER: + case ASM_EVENT_EXCLUSIVE_MMPLAYER: + if ( current_play_sound_event == ASM_EVENT_SHARE_MMPLAYER || + current_play_sound_event == ASM_EVENT_EXCLUSIVE_MMPLAYER ) { + event_src = ASM_EVENT_SOURCE_OTHER_PLAYER_APP; + break; + } + + default: + event_src = ASM_EVENT_SOURCE_OTHER_APP; + break; + } + command = ASM_COMMAND_PAUSE; + } + + /* Execute callback function for monitor handle */ + int monitor_handle = -1; + if (__find_clean_monitor_handle(current_play_instance_id, &monitor_handle)) { + cb_res = __do_callback(current_play_instance_id, monitor_handle, ASM_COMMAND_STOP, event_src); + asm_warning("[ASM_Server] send stop callback for monitor handle of pid %d\n", current_play_instance_id); + if (cb_res != ASM_CB_RES_NONE && cb_res != ASM_CB_RES_STOP) { + asm_error_r("[ASM_Server] oops! not suspected callback result %d\n", cb_res); + } + __set_monitor_dirty(current_play_instance_id); + + /* If current is playing and input event is CALL/VIDEOCALL/ALARM, set to need resume */ + if ((sound_event == ASM_EVENT_CALL || sound_event == ASM_EVENT_VIDEOCALL || sound_event == ASM_EVENT_ALARM) + && (current_play_state == ASM_STATE_PLAYING)) { + __asm_change_need_resume_list(current_play_instance_id, monitor_handle, ASM_NEED_RESUME); + } + } + + /* Execute callback function for worker handle */ + cb_res = __do_callback(current_play_instance_id,current_play_handle,command, event_src); + asm_warning("[ASM_Server] %s(1PAUSE_2PLAY) : Callback of %s: TID(%ld)\n", + __func__,ASM_sound_command_str[command], current_play_instance_id); + /*Change current sound' state when it is in 1Pause_2Play case */ + switch (cb_res) { + case ASM_CB_RES_PAUSE: + update_state = ASM_STATE_PAUSE; + break; + + case ASM_CB_RES_NONE: + case ASM_CB_RES_STOP: + update_state = ASM_STATE_NONE; + update_resource = ASM_RESOURCE_NONE; + break; + + case ASM_CB_RES_IGNORE: + update_state = ASM_STATE_IGNORE; + break; + + default: + asm_error_r("[ASM_Server] oops! not suspected result %d\n", cb_res); + update_state = ASM_STATE_NONE; + break; + } + + /* If current is playing and input event is CALL/VIDEOCALL/ALARM, set to need resume */ + if ((sound_event == ASM_EVENT_CALL || sound_event == ASM_EVENT_VIDEOCALL || sound_event == ASM_EVENT_ALARM) + &&(current_play_state == ASM_STATE_PLAYING)) { + __asm_change_need_resume_list(current_play_instance_id, current_play_handle, ASM_NEED_RESUME); + } + + __asm_change_state_list(current_play_instance_id, current_play_handle, update_state, update_resource); + } + + /* Prepare msg to send */ + ASM_SND_MSG_SET(asm_snd_msg, handle, handle, ASM_COMMAND_PLAY, sound_state); + + if (!updatedflag) { + if (request_id == ASM_REQUEST_REGISTER) { + __asm_register_list(instance_id, handle, sound_event, sound_state, mm_resource); + } else { + __asm_change_state_list(instance_id, handle, sound_state, mm_resource); + } + updatedflag = 1; + } + break; + } + + case ASM_CASE_1PLAY_2PLAY_MIX: + { + if (current_play_instance_id == instance_id) { + asm_info("[ASM_Server] Do not send check resource conflict in same pid %ld\n", instance_id); + } else { + /* MIX but need to check resource conflict */ + asm_warning("[ASM_Server] >>>> __asm_compare_priority_matrix(1PLAY_2PLAY_MIX) : !!!\n"); + ASM_resource_t update_resource = current_using_resource; + unsigned short resource_status = current_using_resource & mm_resource; + if (resource_status) { /* Resouce conflict */ + asm_warning("[ASM_Server] there is system resource conflict 0x%x\n", resource_status); + __print_resource(resource_status); + + /* Execute callback function for monitor handle */ + int monitor_handle = -1; + if (__find_clean_monitor_handle(current_play_instance_id, &monitor_handle)) { + cb_res = __do_callback(current_play_instance_id, monitor_handle, ASM_COMMAND_STOP, ASM_EVENT_SOURCE_RESOURCE_CONFLICT); + if (cb_res != ASM_CB_RES_NONE && cb_res != ASM_CB_RES_STOP) { + asm_error_r("[ASM_Server] oops! not suspected callback result %d\n", cb_res); + } + asm_warning("[ASM_Server] send stop callback for monitor handle of pid %d\n", current_play_instance_id); + __set_monitor_dirty(current_play_instance_id); + + /* If current is playing and input event is CALL/VIDEOCALL/ALARM, set to need resume */ + if ((sound_event == ASM_EVENT_CALL || sound_event == ASM_EVENT_VIDEOCALL || sound_event == ASM_EVENT_ALARM) + && (current_play_state == ASM_STATE_PLAYING) ) { + __asm_change_need_resume_list(current_play_instance_id, monitor_handle, ASM_NEED_RESUME); + } + } + + /* Execute callback function for worker handle */ + /* Stop current resource holding instance */ + cb_res = __do_callback(current_play_instance_id, current_play_handle, ASM_COMMAND_STOP, ASM_EVENT_SOURCE_RESOURCE_CONFLICT); + asm_warning("[ASM_Server] __asm_compare_priority_matrix(1PLAY_2PLAY_MIX) : Resource Conflict : TID(%ld)\n", + current_play_instance_id); + + /* Change current sound */ + switch (cb_res) { + case ASM_CB_RES_NONE: + case ASM_CB_RES_STOP: + update_state = ASM_STATE_NONE; + update_resource = ASM_RESOURCE_NONE; + break; + + case ASM_CB_RES_IGNORE: + update_state = ASM_STATE_IGNORE; + break; + + default: + asm_error_r("[ASM_Server] oops! not suspected result %d\n", cb_res); + update_state = ASM_STATE_NONE; + break; + } + + __asm_change_state_list(current_play_instance_id, current_play_handle, update_state, update_resource); + } + } + + /* Prepare msg to send */ + ASM_SND_MSG_SET(asm_snd_msg, handle, handle, ASM_COMMAND_PLAY, sound_state); + + if (!updatedflag) { + if (request_id == ASM_REQUEST_REGISTER) { + __asm_register_list(instance_id, handle, sound_event, sound_state, mm_resource); + } else { + __asm_change_state_list(instance_id, handle, sound_state, mm_resource); + } + updatedflag = 1; + } + break; + } + + default: + { + ASM_SND_MSG_SET(asm_snd_msg, handle, handle, ASM_COMMAND_NONE, sound_state); + asm_warning("[ASM_Server] >>>> __asm_compare_priority_matrix : ASM_CASE_NONE [It should not be seen] !!!\n"); + break; + } + } /* switch (sound_case) */ + } else { + /* Request was not PLAYING, this means no conflict, just do set */ + asm_info("[ASM_Server] __asm_compare_priority_matrix : No Conflict (Just Register or Set State) !!!\n"); + ASM_SND_MSG_SET(asm_snd_msg, handle, handle, ASM_COMMAND_NONE, sound_state); + + if (sound_state == ASM_STATE_NONE) { + asm_info("[ASM_Server] __asm_compare_priority_matrix(1PLAY_2NONE) : No Conflict !!!\n"); + } else if (sound_state == ASM_STATE_WAITING) { + asm_info("[ASM_Server] __asm_compare_priority_matrix(1PLAY_2WAIT) : No Conflict !!!\n"); + } + + if (!updatedflag) { + if (request_id == ASM_REQUEST_REGISTER) { + __asm_register_list(instance_id, handle, sound_event, sound_state, mm_resource); + } else { + __asm_change_state_list(instance_id, handle, sound_state, mm_resource); + } + updatedflag = 1; + } + } + } /* if (temp_list->sound_state == ASM_STATE_PLAYING) */ + + temp_list = temp_list->next; + + } /* while (temp_list->next != tail_list) */ + + /* Make all monitor handle dirty flag clean. */ + __set_all_monitor_clean(); + } + + /* Find if resource confilct exists in case of 1Pause 2Play or 1Stop 2Play */ + if (ASM_STATUS_NONE != g_sound_status_pause && mm_resource != ASM_RESOURCE_NONE && + (asm_snd_msg.data.result_sound_command == ASM_COMMAND_PLAY || no_conflict_flag)) { + asm_instance_list_t *temp_list = head_list; + int cb_res = 0; + + while (temp_list->next != tail_list) { + /* Who is in PAUSE state? */ + if (temp_list->sound_state == ASM_STATE_PAUSE) { + /* Found PAUSE state */ + asm_warning("[ASM_Server] Now list's state is pause. %d %d\n", instance_id, handle); + ASM_sound_states_t current_play_state = temp_list->sound_state; + ASM_sound_events_t current_play_sound_event = temp_list->sound_event; + long int current_play_instance_id = temp_list->instance_id; + int current_play_handle = temp_list->sound_handle; + ASM_resource_t current_using_resource = temp_list->mm_resource; + + if ((current_play_instance_id == instance_id) && (current_play_handle == handle)) { + if (request_id == ASM_REQUEST_SETSTATE) { + asm_warning("[ASM_Server] Own handle. Pause state change to play. %d %d\n", instance_id, handle); + __asm_change_state_list(instance_id, handle, sound_state, mm_resource); + } else { + asm_warning("[ASM_Server] This is my handle. skip %d %d\n", instance_id, handle); + } + temp_list = temp_list->next; + continue; + } + + if (sound_state == ASM_STATE_PLAYING) { + ASM_sound_cases_t sound_case = ASM_sound_case[current_play_sound_event][sound_event]; + + asm_critical("[ASM_Server] Conflict policy[%x][%x]: %s\n", current_play_sound_event, sound_event, ASM_sound_cases_str[sound_case]); + switch (sound_case) { + case ASM_CASE_1PAUSE_2PLAY: + case ASM_CASE_1STOP_2PLAY: + { + if (current_play_instance_id == instance_id) { + //PID is policy group. + asm_info("[ASM_Server] Do not send Stop callback in same pid %ld\n", instance_id); + } else { + unsigned short resource_status = current_using_resource & mm_resource; + + /* Check conflict with paused instance */ + if (resource_status != ASM_RESOURCE_NONE) { + asm_warning("[ASM_Server] there is system resource conflict with paused instance 0x%x\n",resource_status); + __print_resource(resource_status); + } else { + asm_info("[ASM_Server] no resource conflict with paused instance\n"); + break; + } + + /* Execute callback function for monitor handle */ + int monitor_handle = -1; + if (__find_clean_monitor_handle(current_play_instance_id, &monitor_handle)) { + cb_res = __do_callback(current_play_instance_id, monitor_handle, ASM_COMMAND_STOP, ASM_EVENT_SOURCE_RESOURCE_CONFLICT); + if (cb_res != ASM_CB_RES_NONE && cb_res != ASM_CB_RES_STOP) { + asm_error_r("[ASM_Server] oops! not suspected callback result %d\n", cb_res); + } + asm_warning("[ASM_Server] send stop callback for monitor handle of pid %d\n", current_play_instance_id); + + __set_monitor_dirty(current_play_instance_id); + } + + /* Execute callback function for worker handle */ + cb_res = __do_callback(current_play_instance_id,current_play_handle, ASM_COMMAND_STOP, ASM_EVENT_SOURCE_RESOURCE_CONFLICT); + if (cb_res != ASM_CB_RES_NONE && cb_res != ASM_CB_RES_STOP) { + asm_error_r("[ASM_Server] oops! not suspected result %d\n", cb_res); + } + asm_warning("[ASM_Server] __asm_compare_priority_matrix(1STOP_2PLAY) cause RESOURCE : __do_callback Complete : TID=%ld, handle=%d",current_play_instance_id,current_play_handle ); + + __asm_change_state_list(current_play_instance_id, current_play_handle, ASM_STATE_NONE, ASM_RESOURCE_NONE); + } + + asm_info("[ASM_Server] >>>> __asm_compare_priority_matrix(1STOP_2PLAY) cause RESOURCE : msg sent and then received msg !!!\n"); + break; + } + + default: + { + /* asm_warning("[ASM_Server] >>>> __asm_compare_priority_matrix : ASM_CASE_NONE [do not anything] !!!\n"); */ + break; + } + } /* switch (sound_case) */ + } else { + /* asm_warning("[ASM_Server] >>>> __asm_compare_priority_matrix : ASM_CASE_NONE [do not anything] !!!\n"); */ + } + } /* if (temp_list->sound_state == ASM_STATE_PAUSE) */ + + temp_list = temp_list->next; + } /* while (temp_list->next != tail_list) */ + } + + /* Finally, no conflict */ + if (no_conflict_flag) { + if (request_id == ASM_REQUEST_REGISTER) { + __asm_register_list(instance_id, handle, sound_event, sound_state, mm_resource); + } else { + __asm_change_state_list(instance_id, handle, sound_state, mm_resource); + } + } + + /* Send response to client */ + asm_snd_msg.instance_id = instance_id; + __asm_snd_message(); +} + +void __asm_do_all_resume_callback(ASM_event_sources_t eventsrc) +{ + asm_instance_list_t *temp_list = head_list; + int cb_res = 0; + int avsys_err = 0; + avsys_audio_playing_devcie_t dev = AVSYS_AUDIO_ROUTE_DEVICE_UNKNOWN; + + asm_info("[ASM_Server] __asm_do_all_resume_callback\n"); + + if (AVSYS_FAIL(avsys_err = avsys_audio_get_playing_device_info(&dev))) { + asm_error("[ASM_Server] Can not get playing device info\n"); + } + + while (temp_list->next != tail_list) { + if (temp_list->need_resume == ASM_NEED_RESUME) { + if ((avsys_err != AVSYS_STATE_SUCCESS) || + (dev == AVSYS_AUDIO_ROUTE_DEVICE_HANDSET && temp_list->device_when_interrupted != AVSYS_AUDIO_ROUTE_DEVICE_HANDSET)) { + asm_warning("[ASM_Server] Skip send resume callback. Because sound path has changed to loud during interruption.\n"); + } else { + cb_res = __do_callback(temp_list->instance_id, temp_list->sound_handle, ASM_COMMAND_RESUME, eventsrc); + switch (cb_res) { + case ASM_CB_RES_PLAYING: + temp_list->sound_state = ASM_STATE_PLAYING; + break; + case ASM_CB_RES_IGNORE: + case ASM_CB_RES_NONE: + case ASM_CB_RES_STOP: + case ASM_CB_RES_PAUSE: + default: + /* do nothing */ + break; + } + } + temp_list->need_resume = ASM_NEED_NOT_RESUME; + } + temp_list = temp_list->next; + } +} + +#ifdef USE_SECURITY +gboolean __asm_check_check_privilege (unsigned char* cookie) +{ + int asm_gid = -1; + int retval = 0; + + /* Get ASM server group id */ + asm_gid = security_server_get_gid("asm"); + asm_info ("[Security] asm server gid = [%d]\n", asm_gid); + if (asm_gid < 0) { + asm_error ("[Security] security_server_get_gid() failed. error=[%d]\n", asm_gid); + return false; + } + + /* Check privilege with valid group id */ + retval = security_server_check_privilege((char *)cookie, asm_gid); + if (retval == SECURITY_SERVER_API_SUCCESS) { + asm_info("[Security] security_server_check_privilege() returns [%d]\n", retval); + return true; + } else { + asm_error("[Security] security_server_check_privilege() returns [%d]\n", retval); + return false; + } +} +#endif /* USE_SECURITY */ + +int main() +{ + int pid = 0, ret = 0; + + if (sysconf_set_mempolicy(OOM_IGNORE)) { + fprintf(stderr, "set mem policy failed\n"); + } + signal(SIGPIPE, SIG_IGN); +#if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING) + while (1) { + if (( pid = fork()) < 0) { + asm_critical_r("[ASM_Server]Fork Failed!!!\n"); + return 0; + } else if (pid == 0) { + break; + } else if (pid > 0) { + wait(&ret); + asm_critical_r("[ASM_Server]worker(child) dead!!!, try to refork()"); + } + } +#endif + __asm_create_message_queue(); + + int temp_msgctl_id1 = msgctl(asm_snd_msgid, IPC_RMID, 0); + int temp_msgctl_id2 = msgctl(asm_rcv_msgid, IPC_RMID, 0); + int temp_msgctl_id3 = msgctl(asm_cb_msgid, IPC_RMID, 0); + + + if (temp_msgctl_id1 == -1 || temp_msgctl_id2 == -1 || temp_msgctl_id3 == -1) { + asm_info("[ASM_Server] msgctl failed with error: \n"); + exit(EXIT_FAILURE); + } + //------------------------------------------------------------------- + /* + This is unnessasry finaly, but nessasary during implement. + */ + + __asm_create_message_queue(); + + head_list = (asm_instance_list_t *)malloc(sizeof(asm_instance_list_t)); + tail_list = (asm_instance_list_t *)malloc(sizeof(asm_instance_list_t)); + head_list->next = tail_list; + tail_list->next = tail_list; + + + long int rcv_instance_id; + ASM_requests_t rcv_request_id; + ASM_sound_events_t rcv_sound_event; + ASM_sound_states_t rcv_sound_state; + ASM_resource_t rcv_resource; + int rcv_sound_handle; + + /* + * Init Vconf + */ + if (vconf_set_int(SOUND_STATUS_KEY, 0)) { + asm_critical("[ASM_Server] vconf_set_int fail\n"); + if (vconf_set_int(SOUND_STATUS_KEY, 0)) { + asm_critical_r("[ASM_Server] vconf_set_int fail\n"); + } + } + if (vconf_set_int(HIBERNATION_CHECK_KEY, HIBERNATION_READY)) { + asm_critical("[ASM_Server] Hibernation check vconf_set_int fail\n"); + } + +#ifdef SUPPORT_GCF + if (vconf_get_int(VCONFKEY_ADMIN_GCF_TEST, &is_gcf)) { + asm_warning_r("[ASM_Server] vconf_get_int for VCONFKEY_ADMIN_GCF_TEST failed, set as default\n"); + is_gcf = GCF_DEFAULT; + } +#endif + + while (true) { + asm_info("[ASM_Server] asm_Server is waiting message(%d)!!!\n", asm_is_send_msg_to_cb); + + if (!asm_is_send_msg_to_cb) { + __asm_rcv_message(); + + rcv_instance_id = asm_rcv_msg.instance_id; + rcv_sound_handle = asm_rcv_msg.data.handle; + rcv_request_id = asm_rcv_msg.data.request_id; + rcv_sound_event = asm_rcv_msg.data.sound_event; + rcv_sound_state = asm_rcv_msg.data.sound_state; + rcv_resource = asm_rcv_msg.data.system_resource; + + /*******************************************************************/ + asm_info("[ASM_Server] received msg (tid=%ld,handle=%d,req=%d,event=0x%x,state=0x%x,resource=0x%x)\n", + rcv_instance_id, rcv_sound_handle, rcv_request_id, rcv_sound_event, rcv_sound_state, rcv_resource); + if (rcv_request_id != ASM_REQUEST_EMERGENT_EXIT) { + asm_warning("[ASM_Server] request_id : %s\n", ASM_sound_request_str[rcv_request_id]); + asm_warning("[ASM_Server] sound_event : %s\n", ASM_sound_events_str[rcv_sound_event]); + asm_warning("[ASM_Server] sound_state : %s\n", ASM_sound_state_str[rcv_sound_state]); + asm_warning("[ASM_Server] resource : 0x%x\n", rcv_resource); + } + /*******************************************************************/ + + switch (rcv_request_id) { + case ASM_REQUEST_REGISTER: +#ifdef USE_SECURITY + /* do security check */ + if (__asm_check_check_privilege(asm_rcv_msg.data.cookie) == 0) { + asm_error ("[Security] __asm_check_check_privilege() failed....\n"); + asm_snd_msg.instance_id = rcv_instance_id; + asm_snd_msg.data.alloc_handle = -1; + asm_snd_msg.data.cmd_handle = -1; + asm_snd_msg.data.check_privilege = 0; + __asm_snd_message(); + break; + } + asm_info ("[Security] __asm_check_check_privilege() success\n"); + asm_snd_msg.data.check_privilege = 1; +#endif /* USE_SECURITY */ + __check_dead_process(); + + __asm_get_empty_handle(rcv_instance_id, &rcv_sound_handle); + if (rcv_sound_handle == -1) { + asm_snd_msg.instance_id = rcv_instance_id; + asm_snd_msg.data.alloc_handle = -1; + asm_snd_msg.data.cmd_handle = -1; + __asm_snd_message(); + } else { + __asm_compare_priority_matrix(rcv_instance_id, rcv_sound_handle, rcv_request_id, rcv_sound_event, rcv_sound_state, rcv_resource); + } + + break; + + case ASM_REQUEST_UNREGISTER: + __asm_unregister_list(rcv_sound_handle); + /* only support resuming at end of call & alarm interrupt */ + switch (rcv_sound_event) { + case ASM_EVENT_CALL: + case ASM_EVENT_VIDEOCALL: + __asm_do_all_resume_callback(ASM_EVENT_SOURCE_CALL_END); + break; + case ASM_EVENT_ALARM: + __asm_do_all_resume_callback(ASM_EVENT_SOURCE_ALARM_END); + break; + default: + break; + } + + break; + + case ASM_REQUEST_SETSTATE: + __check_dead_process(); + if ( rcv_sound_state == ASM_STATE_PLAYING ) { + if ( __isItPlayingNow(rcv_instance_id, rcv_sound_handle)) { + __asm_change_state_list(rcv_instance_id, rcv_sound_handle, rcv_sound_state, rcv_resource); + + asm_snd_msg.data.cmd_handle = rcv_sound_handle; + asm_snd_msg.data.result_sound_command = ASM_COMMAND_NONE; + asm_snd_msg.data.result_sound_state = rcv_sound_state; + asm_snd_msg.instance_id = rcv_instance_id; + + __asm_snd_message(); + } else { + __asm_compare_priority_matrix(rcv_instance_id, rcv_sound_handle, rcv_request_id, rcv_sound_event, rcv_sound_state, rcv_resource); + } + __temp_print_list("Set State (Play)"); + } else { + __asm_change_state_list(rcv_instance_id, rcv_sound_handle, rcv_sound_state, rcv_resource); + __temp_print_list("Set State (Not Play)"); + } + break; + + case ASM_REQUEST_GETSTATE: + asm_snd_msg.instance_id = rcv_instance_id; + asm_snd_msg.data.result_sound_state = __asm_find_list(rcv_request_id, rcv_sound_handle); + __asm_snd_message(); + break; + + case ASM_REQUEST_GETMYSTATE: + __check_dead_process(); + asm_snd_msg.instance_id = rcv_instance_id; + asm_snd_msg.data.result_sound_state = __asm_find_process_status(rcv_instance_id); + __asm_snd_message(); + break; + + case ASM_REQUEST_DUMP: + __temp_print_list("DUMP"); + break; + + case ASM_REQUEST_EMERGENT_EXIT: + emergent_exit(rcv_instance_id); + break; + + default: + break; + } + } + } + + return 0; +} + diff --git a/src/audio-session-mgr.c b/src/audio-session-mgr.c new file mode 100644 index 0000000..2178161 --- /dev/null +++ b/src/audio-session-mgr.c @@ -0,0 +1,1252 @@ +/* + * audio-session-manager + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Seungbae Shin <seungbae.shin@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#define CONFIG_ENABLE_MULTI_INSTANCE +#define CONFIG_ENABLE_ASM_SERVER_USING_GLIB +#define CONFIG_ENABLE_SIGNAL_HANDLER +#define CONFIG_ENABLE_RETCB +#define MAKE_HANDLE_FROM_SERVER + +#include <stdio.h> +#include <stdlib.h> +#include <glib.h> +#include <sys/poll.h> +#include <sys/syscall.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <poll.h> +#include <string.h> + +#ifdef USE_SECURITY +#include <security-server.h> +#endif + +#if defined(USE_VCONF) +#include <vconf.h> +#include <errno.h> +#else +#include <gconf/gconf.h> +#include <gconf/gconf-client.h> +#include <phonestatus.h> + +#endif +#include "../include/audio-session-manager.h" +#include "../include/asm-log.h" + +#define asmgettid() (long int)getpid() +#define ASM_HANDLE_MAX 256 + +#define NO_EINTR(stmt) while ((stmt) == -1 && errno == EINTR); /* sample code by THE LINUX PROGRAMMING INTERFACE */ + +int asm_register_instance_id; + +int asm_snd_msgid; +int asm_rcv_msgid; +int asm_cb_msgid; + +ASM_msg_lib_to_asm_t asm_snd_msg; +ASM_msg_asm_to_lib_t asm_rcv_msg; +ASM_msg_asm_to_cb_t asm_cb_msg; + +ASM_sound_cb_t asm_callback; + +unsigned char str_pass[] = "< OK >"; +unsigned char str_fail[] = "<FAIL>"; + +typedef gboolean (*gLoopPollHandler_t)(gpointer d); + +typedef struct +{ + ASM_sound_events_t sound_event; + int asm_fd; + ASM_sound_cb_t asm_callback; + void *cb_data; + int asm_tid; + int handle; + bool is_used; + GSource* asm_src; + guint ASM_g_id; +} ASM_sound_ino_t; + +ASM_sound_ino_t ASM_sound_handle[ASM_HANDLE_MAX]; + +static const char* ASM_sound_events_str[] = +{ + "SHARE_MMPLAYER", + "SHARE_MMCAMCORDER", + "SHARE_MMSOUND", + "SHARE_OPENAL", + "SHARE_AVSYSTEM", + "EXCLUSIVE_MMPLAYER", + "EXCLUSIVE_MMCAMCORDER", + "EXCLUSIVE_MMSOUND", + "EXCLUSIVE_OPENAL", + "EXCLUSIVE_AVSYSTEM", + "NOTIFY", + "CALL", + "SHARE_FMRADIO", + "EXCLUSIVE_FMRADIO", + "EARJACK_UNPLUG", + "ALARM", + "VIDEOCALL", + "MONITOR" +}; + +static const char* ASM_sound_cases_str[] = +{ + "CASE_NONE", + "CASE_1PLAY_2STOP", + "CASE_1PLAY_2ALTER_PLAY", + "CASE_1PLAY_2WAIT", + "CASE_1ALTER_PLAY_2PLAY", + "CASE_1STOP_2PLAY", + "CASE_1PAUSE_2PLAY", + "CASE_1VIRTUAL_2PLAY", + "CASE_1PLAY_2PLAY_MIX" +}; + +static const char* ASM_sound_state_str[] = +{ + "STATE_NONE", + "STATE_PLAYING", + "STATE_WAITING", + "STATE_STOP", + "STATE_PAUSE", + "STATE_PAUSE_BY_APP", + "STATE_ALTER_PLAYING" +}; + +/* + * function prototypes + */ + + +unsigned int ASM_all_sound_status; + +void __asm_init_module(void); +void __asm_fini_module(void); +int __ASM_find_index(int handle); + +bool __ASM_get_sound_state(unsigned int *all_sound_status, int *error_code) +{ + int value = 0; + + if(vconf_get_int(SOUND_STATUS_KEY, &value)) { + asm_error_r("[Error = %d] __ASM_get_sound_state => phonestatus_get \n", ERR_ASM_VCONF_ERROR); + return false; + } + asm_info(" __ASM_get_sound_state : All status(%#X) \n", value); + *all_sound_status = value; + ASM_all_sound_status = value; + + return true; +} + +bool __ASM_set_sound_state(ASM_sound_events_t sound_event, ASM_sound_states_t sound_state, int *error_code) +{ + /* this function will deprecated */ + asm_info(" __ASM_set_sound_state : Event(%s), State(%s)\n", + ASM_sound_events_str[sound_event], ASM_sound_state_str[sound_state]); + + return true; +} + +gboolean __asm_fd_check(GSource * source) +{ + GSList *fd_list; + fd_list = source->poll_fds; + GPollFD *temp; + + do { + temp = (GPollFD*)fd_list->data; + if (temp->revents & (POLLIN | POLLPRI)) + return TRUE; + fd_list = fd_list->next; + } while (fd_list); + + return FALSE; /* there is no change in any fd state */ +} + + +gboolean __asm_fd_prepare(GSource *source, gint *timeout) +{ + return FALSE; +} + +gboolean __asm_fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + callback(user_data); + return TRUE; +} + +gboolean asm_callback_handler( gpointer d) +{ + GPollFD *data = (GPollFD*)d; + unsigned int buf; + int count; + int tid = 0; + int asm_index = 0; + asm_info("asm_callback_handler"); + + if (data->revents & (POLLIN | POLLPRI)) { + int handle; + int error_code = 0; + int event_src; + unsigned int sound_status_value; + ASM_sound_commands_t rcv_command; + ASM_cb_result_t cb_res = ASM_CB_RES_NONE; + + + count = read(data->fd, &buf, sizeof(int)); + + handle = (int)( buf & 0x0000ffff); + rcv_command = (ASM_sound_commands_t)((buf >> 16) & 0x0f); + event_src = (ASM_event_sources_t)((buf >> 24) & 0x0f); + + asm_index = __ASM_find_index(handle); + if (asm_index == -1) { + asm_critical_r("asm_callback_handler : Can not find index\n"); + return false; + } + + tid = ASM_sound_handle[asm_index].asm_tid; + + if (rcv_command) { + asm_critical("[RETCB] got and start CB : TID(%d), handle(%d) cmd(%d) event_src(%d)\n", tid, handle, rcv_command, event_src ); + if (!__ASM_get_sound_state(&sound_status_value, &error_code)) { + asm_info("[ASM_CB][Error = %d] asm_callback_handler : ASM_set_sound_state => __ASM_get_sound_state \n", error_code); + } + switch (rcv_command) { + case ASM_COMMAND_PLAY: + case ASM_COMMAND_RESUME: + case ASM_COMMAND_PAUSE: + case ASM_COMMAND_STOP: + if (ASM_sound_handle[asm_index].asm_callback == NULL) { + asm_info("callback is null!!!!\n"); + return FALSE; + } + asm_info("ASM callback function pointer - start(%p)\n",ASM_sound_handle[asm_index].asm_callback); + if (ASM_sound_handle[asm_index].asm_callback != NULL) { + cb_res = (ASM_sound_handle[asm_index].asm_callback)(handle, event_src, rcv_command, sound_status_value, ASM_sound_handle[asm_index].cb_data); + } else { + asm_info("[ASM_CB][RETCB]callback in null(possibly unregistered simultaneously)\n"); + } + asm_info("[ASM_CB][RETCB]callback - end\n"); + break; + default: + break; + } +#ifdef CONFIG_ENABLE_RETCB + int rett = 0; + int buf = cb_res; + int tmpfd = -1; + char *filename2 = g_strdup_printf("/tmp/ASM.%d.%dr", ASM_sound_handle[asm_index].asm_tid, handle); + tmpfd = open(filename2, O_WRONLY | O_NONBLOCK); + if (tmpfd < 0) { + char str_error[256]; + strerror_r(errno, str_error, sizeof(str_error)); + asm_error("[ASM_CB][RETCB][Failed(May Server Close First)]tid(%d) fd(%d) %s errno=%d(%s)\n", tid, tmpfd, filename2, errno, str_error); + g_free(filename2); + return FALSE; + } + rett = write(tmpfd, &buf, sizeof(buf)); + close(tmpfd); + g_free(filename2); + asm_info("[RETCB]tid(%d) finishing CB (write=%d)\n", tid, rett); +#endif + } + } + return TRUE; +} + +bool __ASM_add_sound_callback(int index, int fd, gushort events, gLoopPollHandler_t p_gloop_poll_handler ) +{ + GSource* cmd_fd_gsrc = NULL; + GSourceFuncs *src_funcs = NULL; /* handler function */ + guint gsource_handle; + GPollFD *g_fd_cmd = NULL; /* file descriptor */ + + /* 1. make GSource Object */ + src_funcs = (GSourceFuncs *)g_malloc(sizeof(GSourceFuncs)); + if (!src_funcs) { + asm_info(" __ASM_add_sound_callback : g_malloc failed on g_src_funcs"); + return false; + } + src_funcs->prepare = __asm_fd_prepare; + src_funcs->check = __asm_fd_check; + src_funcs->dispatch = __asm_fd_dispatch; + src_funcs->finalize = NULL; + cmd_fd_gsrc = g_source_new(src_funcs, sizeof(GSource)); + if (!cmd_fd_gsrc) { + asm_critical(" __ASM_add_sound_callback : g_malloc failed on m_readfd"); + return false; + } + ASM_sound_handle[index].asm_src = cmd_fd_gsrc; + + /* 2. add file description which used in g_loop() */ + g_fd_cmd = (GPollFD *)g_malloc(sizeof(GPollFD)); + g_fd_cmd->fd = fd; + g_fd_cmd->events = events; + + /* 3. combine g_source object and file descriptor */ + g_source_add_poll(cmd_fd_gsrc, g_fd_cmd); + gsource_handle = g_source_attach(cmd_fd_gsrc, NULL); + if (!gsource_handle) { + asm_critical(" __ASM_add_sound_callback : Error: Failed to attach the source to context"); + return false; + } + + asm_info(" g_source_add_poll : g_src_id(%d)\n", gsource_handle); + ASM_sound_handle[index].ASM_g_id = gsource_handle; + + /* 4. set callback */ + g_source_set_callback(cmd_fd_gsrc, p_gloop_poll_handler,(gpointer)g_fd_cmd, NULL); + + asm_info(" g_source_set_callback : %d\n", errno); + return true; +} + + +bool __ASM_remove_sound_callback(int index, gushort events) +{ + bool ret; + GPollFD *g_fd_cmd = NULL; /* store file descriptor */ + + g_fd_cmd = (GPollFD *)g_malloc(sizeof(GPollFD)); + g_fd_cmd->fd = ASM_sound_handle[index].asm_fd; + g_fd_cmd->events = events; + + asm_info(" g_source_remove_poll : fd(%d), event(%#x)\n", g_fd_cmd->fd, g_fd_cmd->events); + g_source_remove_poll(ASM_sound_handle[index].asm_src, g_fd_cmd); + asm_info(" g_source_remove_poll : %d\n", errno); + ret = g_source_remove(ASM_sound_handle[index].ASM_g_id); + asm_info(" g_source_remove : ret(%#X)\n", ret); + + ASM_sound_handle[index].ASM_g_id = 0; + ASM_sound_handle[index].asm_src = NULL; + ASM_sound_handle[index].asm_callback = NULL; + + return true; +} + +int __ASM_find_index(int handle) +{ + int i = 0; + for(i = 0; i< ASM_HANDLE_MAX; i++) { + if (handle == ASM_sound_handle[i].handle) + return i; + } + return -1; +} + +void __ASM_add_callback(int index) +{ + __ASM_add_sound_callback(index, ASM_sound_handle[index].asm_fd, (gushort)POLLIN | POLLPRI, asm_callback_handler); +} + + +void __ASM_remove_callback(int index) +{ + __ASM_remove_sound_callback(index, (gushort)POLLIN | POLLPRI); +} + + +void __ASM_open_callback(int index) +{ + mode_t pre_mask; + + asm_info(" __ASM_open_callback : index (%d)\n", index); + char *filename = g_strdup_printf("/tmp/ASM.%d.%d", ASM_sound_handle[index].asm_tid, ASM_sound_handle[index].handle); + pre_mask = umask(0); + mknod(filename, S_IFIFO|0666, 0); + umask(pre_mask); + ASM_sound_handle[index].asm_fd = open( filename, O_RDWR|O_NONBLOCK); + if (ASM_sound_handle[index].asm_fd == -1) + asm_info(" __ASM_open_callback %s : file open error(%d)\n", str_fail, errno); + else + asm_info(" __ASM_open_callback : %s : filename(%s), fd(%d)\n", str_pass, filename, ASM_sound_handle[index].asm_fd); + g_free(filename); + +#ifdef CONFIG_ENABLE_RETCB + char *filename2 = g_strdup_printf("/tmp/ASM.%d.%dr", ASM_sound_handle[index].asm_tid, ASM_sound_handle[index].handle); + pre_mask = umask(0); + mknod(filename2, S_IFIFO | 0666, 0); + umask(pre_mask); + g_free(filename2); +#endif + +} + + +void __ASM_close_callback(int index) +{ + asm_info(" __ASM_close_callback : index (%d)\n", index); + if (ASM_sound_handle[index].asm_fd < 0) { + asm_info(" __ASM_close_callback : %s : fd error.\n", str_fail); + } else { + char *filename = g_strdup_printf("/tmp/ASM.%d.%d", ASM_sound_handle[index].asm_tid, ASM_sound_handle[index].handle); + close(ASM_sound_handle[index].asm_fd); + remove(filename); + asm_info(" __ASM_close_callback : %s : filename(%s), fd(%d)\n", str_pass, filename, ASM_sound_handle[index].asm_fd); + g_free(filename); + } + +#ifdef CONFIG_ENABLE_RETCB + char *filename2 = g_strdup_printf("/tmp/ASM.%d.%dr", ASM_sound_handle[index].asm_tid, ASM_sound_handle[index].handle); + + /* Defensive code - wait until callback timeout although callback is removed */ + int buf = ASM_CB_RES_STOP; + int tmpfd = -1; + + tmpfd = open(filename2, O_WRONLY | O_NONBLOCK); + if (tmpfd < 0) { + char str_error[256]; + strerror_r(errno, str_error, sizeof(str_error)); + asm_error("[__ASM_close_callback][Failed(May Server Close First)]tid(%d) fd(%d) %s errno=%d(%s)\n", + ASM_sound_handle[index].asm_tid, tmpfd, filename2, errno, str_error); + } else { + asm_info("write ASM_CB_RES_STOP(tid:%d) for waiting server\n", ASM_sound_handle[index].asm_tid); + write(tmpfd, &buf, sizeof(buf)); + close(tmpfd); + } + + remove(filename2); + g_free(filename2); +#endif + +} + +bool __asm_construct_snd_msg(int asm_pid, int handle, ASM_sound_events_t sound_event, + ASM_requests_t request_id, ASM_sound_states_t sound_state, ASM_resource_t resource, int *error_code) +{ + asm_snd_msg.instance_id = asm_pid; + + asm_snd_msg.data.handle = handle; + asm_snd_msg.data.request_id = request_id; + asm_snd_msg.data.sound_event = sound_event; + asm_snd_msg.data.sound_state = sound_state; + asm_snd_msg.data.system_resource = resource; + + asm_info(" ASM_Lib send message (tid=%ld,handle=%d,req=%d,evt=%d,state=%d,resource=%d)\n", asm_snd_msg.instance_id, asm_snd_msg.data.handle, + asm_snd_msg.data.request_id, asm_snd_msg.data.sound_event, asm_snd_msg.data.sound_state, asm_snd_msg.data.system_resource); + asm_info(" instance_id : %ld\n", asm_snd_msg.instance_id); + asm_info(" handle : %d\n", asm_snd_msg.data.handle); + + return true; +} + + +bool __ASM_init_msg(int *error_code) +{ + asm_snd_msgid = msgget((key_t)2014, 0666); + asm_rcv_msgid = msgget((key_t)4102, 0666); + asm_cb_msgid = msgget((key_t)4103, 0666); + + + asm_info(" __asm_init !! : snd_msqid(%#X), rcv_msqid(%#X), cb_msqid(%#X)\n", asm_snd_msgid, + asm_rcv_msgid, asm_cb_msgid); + + + if (asm_snd_msgid == -1 || asm_rcv_msgid == -1 || asm_cb_msgid == -1 ) { + *error_code = ERR_ASM_MSG_QUEUE_MSGID_GET_FAILED; + asm_info(" __ASM_init : Msgget failed with error.\n"); + return false; + } + + return true; +} + +void __ASM_init_callback(int index) +{ + __ASM_open_callback(index); + __ASM_add_callback(index); +} + + +void __ASM_destroy_callback(int index) +{ + asm_info(" __ASM_destroy_callback !!\n"); + __ASM_remove_callback(index); + __ASM_close_callback(index); +} + +#ifdef USE_SECURITY +bool __ASM_set_cookie (unsigned char* cookie) +{ + int retval = -1; + int cookie_size = 0; + asm_info ("<<<< [%s]\n", __func__); + + cookie_size = security_server_get_cookie_size(); + if (cookie_size != COOKIE_SIZE) { + asm_error ("[Security] security_server_get_cookie_size(%d) != COOKIE_SIZE(%d)\n", cookie_size, COOKIE_SIZE); + return false; + } + + retval = security_server_request_cookie (cookie, COOKIE_SIZE); + if (retval == SECURITY_SERVER_API_SUCCESS) { + asm_info ("[Security] security_server_request_cookie() returns [%d]\n", retval); + return true; + } else { + asm_error ("[Security] security_server_request_cookie() returns [%d]\n", retval); + return false; + } +} +#endif + +EXPORT_API +bool ASM_register_sound(const int application_pid, int *asm_handle, ASM_sound_events_t sound_event, ASM_sound_states_t sound_state, ASM_sound_cb_t callback, void *cb_data, ASM_resource_t mm_resource, int *error_code) +{ + int error = 0; + unsigned int sound_status_value; + int handle = 0; + int asm_pid = 0; + int index = 0; + int ret = 0; + unsigned int rcv_sound_status_value; + + if (error_code==NULL) { + asm_error_r("[Error] ASM_register_sound : invalid parameter. \n"); + return false; + } + + if (sound_event< ASM_EVENT_SHARE_MMPLAYER || sound_event >= ASM_EVENT_MAX) { + *error_code = ERR_ASM_EVENT_IS_INVALID; + asm_error_r("[Error] ASM_register_sound : invalid sound event \n"); + return false; + } + + for (index = 0; index < ASM_HANDLE_MAX; index++) { + if (ASM_sound_handle[index].is_used == FALSE) { + break; + } + } + + if (index == ASM_HANDLE_MAX) { + *error_code = ERR_ASM_EVENT_IS_FULL; + asm_error_r("[Error] >>>> ASM_register_sound : local sound event is full(MAX) \n"); + return false; + } + + if (application_pid == -1) { + asm_pid = asmgettid(); + } else if (application_pid > 2) { + asm_pid = application_pid; + } else { + *error_code = ERR_ASM_INVALID_PARAMETER; + asm_error_r("[Error] >>>> ASM_register_sound : invalid pid %d\n", application_pid); + return false; + } + + ASM_sound_handle[index].sound_event = sound_event; + ASM_sound_handle[index].asm_tid = asm_pid; + + asm_info(" <<<< ASM_register_sound : Event(%s), Tid(%d), Index(%d) \n", ASM_sound_events_str[sound_event], ASM_sound_handle[index].asm_tid, index); + + if (!__ASM_init_msg(&error)) { + asm_error("[Error = %d] >>>> ASM_register_sound =>__asm_init \n", error); + } + + if (!__ASM_get_sound_state(&sound_status_value, error_code)) { + asm_error("[Error = %d] >>>> ASM_register_sound => __ASM_get_sound_state \n", *error_code); + } + + /* If state is PLAYING, do set state immediately */ + if (sound_state == ASM_STATE_PLAYING) { + asm_info(" <<<< ASM_register_sound : Event(%s), Tid(%d), State(PLAYING) \n", ASM_sound_events_str[sound_event], ASM_sound_handle[index].asm_tid); + if (!__ASM_set_sound_state(sound_event, ASM_STATE_PLAYING, error_code)) { + asm_error_r("[Error = %d] >>>> ASM_register_sound => __ASM_set_sound_state(PLAYING) \n", *error_code); + return false; + } + } else { + asm_info(" <<<< ASM_register_sound : Event(%s), Tid(%ld), State(WAITING) \n", ASM_sound_events_str[sound_event], asmgettid()); + } + + + handle = -1; /* for register & get handle from server */ + +#ifdef USE_SECURITY + /* get cookie from security server */ + if (__ASM_set_cookie (asm_snd_msg.data.cookie) == false) + return false; +#endif + + /* Construct msg to send -> send msg -> recv msg */ + if (!__asm_construct_snd_msg(asm_pid, handle, sound_event, ASM_REQUEST_REGISTER, sound_state, mm_resource, error_code)) { + asm_error_r("[Error] >>>> ASM_register_sound : Send msg construct failed.\n"); + return false; + } + NO_EINTR(ret = msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_SND_ERROR; + asm_error_r("[Error] >>>> ASM_register_sound : Msgsnd failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + NO_EINTR(ret = msgrcv(asm_rcv_msgid, (void *)&asm_rcv_msg, sizeof(asm_rcv_msg.data), asm_pid, 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_RCV_ERROR; + asm_error_r("[Error] >>>> ASM_register_sound : Msgrcv failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + /* Construct msg to send -> send msg -> recv msg : end */ + +#ifdef USE_SECURITY + /* Check privilege first */ + if (asm_rcv_msg.data.check_privilege == 0) { + asm_error_r("[Security] Check privilege from server Failed!!!\n"); + *error_code = ERR_ASM_CHECK_PRIVILEGE_FAILED; + return false; + } else { + asm_info ("[Security] Check privilege from server Success"); + } +#endif + + handle = asm_rcv_msg.data.alloc_handle; /* get handle from server */ + if (handle == -1) { + asm_error_r("[Error] >>> ASM_register_sound : Create handle from server failed\n"); + *error_code = ERR_ASM_HANDLE_IS_FULL; + return false; + } + + ASM_sound_handle[index].handle = handle; + + __ASM_init_callback(index); + + asm_info( "ASM_register_sound \n"); +/********************************************************************************************************/ + switch (asm_rcv_msg.data.result_sound_command) { + case ASM_COMMAND_PAUSE: + case ASM_COMMAND_STOP: + if (handle == asm_rcv_msg.data.cmd_handle) { + + + __ASM_destroy_callback(index); + + ASM_sound_handle[index].asm_fd = 0; + ASM_sound_handle[index].asm_tid = 0; + ASM_sound_handle[index].sound_event = ASM_EVENT_NONE; + ASM_sound_handle[index].is_used = FALSE; + + *error_code = ERR_ASM_POLICY_CANNOT_PLAY; + return false; + } else { + int action_index = 0; + + if (!__ASM_get_sound_state(&rcv_sound_status_value, error_code)) { + asm_error("[ASM_CB][Error = %d] asm_callback_handler : ASM_set_sound_state => __ASM_get_sound_state \n", *error_code); + } + + asm_info("[ASM_CB] asm_callback_handler : Callback : TID(%ld), handle(%d)\n", asm_rcv_msg.instance_id, asm_rcv_msg.data.cmd_handle); + action_index = __ASM_find_index(asm_rcv_msg.data.cmd_handle); + if (action_index == -1) { + asm_error("[ASM_CB] Can not find index of instance %ld, handle %d\n", asm_rcv_msg.instance_id, asm_rcv_msg.data.cmd_handle); + } else { + if (ASM_sound_handle[action_index].asm_callback!=NULL) { + ASM_sound_handle[action_index].asm_callback(asm_rcv_msg.data.cmd_handle, ASM_sound_handle[action_index].sound_event, asm_rcv_msg.data.result_sound_command, rcv_sound_status_value, ASM_sound_handle[action_index].cb_data); + } else { + asm_info("[ASM_CB] null callback"); + } + } + } + break; + + case ASM_COMMAND_PLAY: + case ASM_COMMAND_NONE: + case ASM_COMMAND_RESUME: + default: + break; + } +/********************************************************************************************************/ + + + ASM_sound_handle[index].asm_callback = callback; + ASM_sound_handle[index].cb_data = cb_data; + ASM_sound_handle[index].is_used = TRUE; + + asm_info(" >>>> ASM_register_sound : Event(%s), Handle(%d), CBFuncPtr(%p) \n", ASM_sound_events_str[sound_event], handle, callback); + /* Add [out] param, asm_handle */ + *asm_handle = handle; + + return true; + +} + +EXPORT_API +bool ASM_change_callback(const int asm_handle, ASM_sound_events_t sound_event, ASM_sound_cb_t callback, void *cb_data, int *error_code) +{ + int handle=0; + + if (error_code==NULL) { + asm_error_r("[Error] ASM_unregister_sound : invalid parameter. \n"); + return false; + } + + if (sound_event < ASM_EVENT_SHARE_MMPLAYER || sound_event >= ASM_EVENT_MAX) { + *error_code = ERR_ASM_EVENT_IS_INVALID; + asm_error_r("[Error] ASM_unregister_sound : invalid sound event \n"); + return false; + } + + int asm_index = -1; + + if (asm_handle < 0 || asm_handle >= ASM_SERVER_HANDLE_MAX) { + *error_code = ERR_ASM_POLICY_INVALID_HANDLE; + asm_error_r("[Error] >>>> invalid handle %d. callback is not registered\n", asm_handle); + return false; + } + + handle = asm_handle; + + asm_index = __ASM_find_index(handle); + if (asm_index == -1) { + *error_code = ERR_ASM_POLICY_INVALID_HANDLE; + asm_error_r("[Error] >>>> Can not find index for handle %d [%d]\n", handle, __LINE__); + return false; + } + + asm_info("callback function has changed to %p\n", callback); + ASM_sound_handle[asm_index].asm_callback = callback; + ASM_sound_handle[asm_index].cb_data = cb_data; + + return true; +} + + +EXPORT_API +bool ASM_unregister_sound(const int asm_handle, ASM_sound_events_t sound_event, int *error_code) +{ + int handle=0; + int asm_index = -1; + int ret = 0; + + if (error_code==NULL) { + asm_error_r("[Error] ASM_unregister_sound : invalid parameter. \n"); + return false; + } + + if (sound_event<ASM_EVENT_SHARE_MMPLAYER || sound_event >= ASM_EVENT_MAX) { + *error_code = ERR_ASM_EVENT_IS_INVALID; + asm_error_r("[Error] ASM_unregister_sound : invalid sound event %d\n", sound_event); + return false; + } + + if (asm_handle < 0 || asm_handle >= ASM_SERVER_HANDLE_MAX) { + *error_code = ERR_ASM_POLICY_INVALID_HANDLE; + asm_error_r("[Error] >>>> invalid handle %d. callback is not registered\n", asm_handle); + return false; + } + + handle = asm_handle; + asm_index = __ASM_find_index(handle); + if (asm_index == -1) { + *error_code = ERR_ASM_POLICY_INVALID_HANDLE; + asm_error_r("[Error] >>>> Can not find index for handle %d [%d]\n", handle, __LINE__); + return false; + } + asm_info("<<<< ASM_unregister_sound : Event(%s), Tid(%d), Handle(%d) Index(%d)\n", + ASM_sound_events_str[sound_event], ASM_sound_handle[asm_index].asm_tid, ASM_sound_handle[asm_index].handle, asm_index); + + if (!__asm_construct_snd_msg(ASM_sound_handle[asm_index].asm_tid, handle, sound_event, ASM_REQUEST_UNREGISTER, ASM_STATE_NONE, ASM_RESOURCE_NONE, error_code)) { + asm_error_r(">>>> Send msg construct failed.\n"); + return false; + } + + NO_EINTR(ret = msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_SND_ERROR; + asm_error_r("[Error] >>>> ASM_unregister_sound : Msgsnd failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + + __ASM_destroy_callback(asm_index); + + ASM_sound_handle[asm_index].asm_fd = 0; + ASM_sound_handle[asm_index].asm_tid = 0; + ASM_sound_handle[asm_index].sound_event = ASM_EVENT_NONE; + ASM_sound_handle[asm_index].is_used = FALSE; + + asm_info(">>>> ASM_unregister_sound : Event(%s) \n", ASM_sound_events_str[sound_event]); + + return true; +} + +EXPORT_API +bool ASM_get_sound_status(unsigned int *all_sound_status, int *error_code) +{ + if (all_sound_status == NULL || error_code == NULL) { + if (error_code) + *error_code = ERR_ASM_UNKNOWN_ERROR; + asm_error_r("[Error] ASM_get_sound_status : invalid parameter \n"); + return false; + } + + asm_info("<<<< ASM_get_sound_status : Tid(%ld) \n", asmgettid()); + + if (!__ASM_get_sound_state(all_sound_status, error_code)) { + asm_error_r("[Error = %d] >>>> ASM_get_sound_status => __ASM_get_sound_state \n", *error_code); + return false; + } + + asm_info(">>>> ASM_get_sound_status : All status(%#X) \n", *all_sound_status); + + return true; +} + +EXPORT_API +bool ASM_get_process_session_state(const int asm_handle, ASM_sound_states_t *sound_state, int *error_code) +{ + int handle = 0; + int asm_index = 0; + int ret = 0; + + if (sound_state == NULL || error_code == NULL) { + if (error_code) + *error_code = ERR_ASM_UNKNOWN_ERROR; + asm_error_r("[Error] ASM_get_process_session_state : invalid parameter \n"); + return false; + } + + handle = asm_handle; + asm_index = __ASM_find_index(handle); + if (asm_index == -1) { + asm_error_r("Can not find index of %d [%d]\n", handle, __LINE__); + return false; + } + + + asm_info("<<<< ASM_get_process_session_state : Pid(%d)\n", ASM_sound_handle[asm_index].asm_tid); + + if (!__asm_construct_snd_msg(ASM_sound_handle[asm_index].asm_tid, handle, ASM_EVENT_MONITOR, ASM_REQUEST_GETMYSTATE, ASM_STATE_NONE, ASM_RESOURCE_NONE, error_code)) { + asm_error_r("[Error] >>>> ASM_get_sound_state : Send msg construct failed.\n"); + return false; + } + + + NO_EINTR(ret = msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_SND_ERROR; + asm_error_r("[Error] >>>> ASM_get_process_session_state : Msgsnd failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + + NO_EINTR(ret = msgrcv(asm_rcv_msgid, (void *)&asm_rcv_msg, sizeof(asm_rcv_msg.data), asm_snd_msg.instance_id, 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_RCV_ERROR; + asm_error_r("[Error] >>>> ASM_get_process_session_state : Msgrcv failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + + *sound_state = asm_rcv_msg.data.result_sound_state; + + asm_info(">>>> ASM_get_process_session_state : Pid(%d), State(%s) \n", ASM_sound_handle[asm_index].asm_tid, ASM_sound_state_str[*sound_state]); + + + return true; +} + +EXPORT_API +bool ASM_get_sound_state(const int asm_handle, ASM_sound_events_t sound_event, ASM_sound_states_t *sound_state, int *error_code) +{ + int handle = 0; + int asm_index = 0; + int ret = 0; + + if (sound_state == NULL || error_code == NULL) { + if (error_code) + *error_code = ERR_ASM_UNKNOWN_ERROR; + asm_error_r("[Error] ASM_get_sound_state : invalid parameter \n"); + return false; + } + if (sound_event < ASM_EVENT_SHARE_MMPLAYER || sound_event >= ASM_EVENT_MAX) { + *error_code = ERR_ASM_EVENT_IS_INVALID; + asm_error_r("[Error] ASM_get_sound_state : invalid sound event (%x)\n",sound_event); + return false; + } + handle = asm_handle; + + asm_index = __ASM_find_index(handle); + if (asm_index == -1) { + asm_error_r("Can not find index of %d [%d]\n", handle, __LINE__); + return false; + } + asm_info("<<<< ASM_get_sound_state : Event(%s), Tid(%d), handle(%d)\n", + ASM_sound_events_str[sound_event], ASM_sound_handle[asm_index].asm_tid, ASM_sound_handle[asm_index].handle); + + if (!__asm_construct_snd_msg(ASM_sound_handle[asm_index].asm_tid, handle, sound_event, ASM_REQUEST_GETSTATE, ASM_STATE_NONE, ASM_RESOURCE_NONE, error_code)) { + asm_error_r("[Error] >>>> ASM_get_sound_state : Send msg construct failed.\n"); + return false; + } + + + NO_EINTR(ret = msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_SND_ERROR; + asm_error_r("[Error] >>>> ASM_get_sound_state : Msgsnd failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + + NO_EINTR(ret = msgrcv(asm_rcv_msgid, (void *)&asm_rcv_msg, sizeof(asm_rcv_msg.data), asm_snd_msg.instance_id, 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_RCV_ERROR; + asm_error_r("[Error] >>>> ASM_get_sound_state : Msgrcv failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + + *sound_state = asm_rcv_msg.data.result_sound_state; + + asm_info(">>>> ASM_get_sound_state : Event(%s), State(%s) \n", + ASM_sound_events_str[sound_event], ASM_sound_state_str[*sound_state]); + + + return true; +} + + +EXPORT_API +bool ASM_set_sound_state(const int asm_handle, ASM_sound_events_t sound_event, ASM_sound_states_t sound_state, ASM_resource_t mm_resource, int *error_code) +{ + int handle = 0; + int asm_index = 0; + int ret = 0; + unsigned int rcv_sound_status_value; + + asm_info("<<<< ASM_set_sound_state \n"); + if (error_code == NULL) { + asm_error_r("error_code is null \n"); + return false; + } + + if (sound_event < 0 || sound_event > ASM_PRIORITY_MATRIX_MIN) { + asm_error_r(" ASM_set_sound_state(%x,%x) arg is out of bound!!\n", sound_event, sound_state); + *error_code = ERR_ASM_EVENT_IS_INVALID; + return false; + } + + if (asm_handle < 0 || asm_handle >= ASM_SERVER_HANDLE_MAX) { + *error_code = ERR_ASM_POLICY_INVALID_HANDLE; + asm_error_r("[Error] ASM_set_sound_state : Invalid handle %d \n", asm_handle); + return false; + } + + handle = asm_handle; + + asm_index = __ASM_find_index(handle); + if (asm_index == -1) { + asm_error_r("Can not find index of %d [%d]\n", handle, __LINE__); + return false; + } + + asm_info("<<<< ASM_set_sound_state : Event(%s), State(%s), Tid(%d), handle(%d) \n", + ASM_sound_events_str[sound_event], ASM_sound_state_str[sound_state], ASM_sound_handle[asm_index].asm_tid, ASM_sound_handle[asm_index].handle); + + + if (!__asm_construct_snd_msg(ASM_sound_handle[asm_index].asm_tid, ASM_sound_handle[asm_index].handle, sound_event, ASM_REQUEST_SETSTATE, sound_state, mm_resource, error_code)) { + asm_error_r("[Error] >>>> ASM_set_sound_state : Send msg construct failed.\n"); + return false; + } + + NO_EINTR(ret = msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_SND_ERROR; + asm_error_r("[Error] >>>> ASM_set_sound_state : Msgsnd failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + + if (sound_state == ASM_STATE_PLAYING ) { + NO_EINTR(ret = msgrcv(asm_rcv_msgid, (void *)&asm_rcv_msg, sizeof(asm_rcv_msg.data), ASM_sound_handle[handle].asm_tid, 0)); + if (ret == -1) { + *error_code = ERR_ASM_MSG_QUEUE_RCV_ERROR; + asm_error_r("[Error] >>>> ASM_set_sound_state : Msgrcv failed (%d,%s) \n", errno, strerror(errno)); + return false; + } + + asm_info( " <<<<<<<<<<<<<<<< [BEFORE] Callback : Main Context >>>>>>>>>>>>>>>>>>>> \n"); + /********************************************************************************************************/ + switch (asm_rcv_msg.data.result_sound_command) { + case ASM_COMMAND_PAUSE: + case ASM_COMMAND_STOP: + if (handle == asm_rcv_msg.data.cmd_handle) { + + asm_index = __ASM_find_index(asm_rcv_msg.data.cmd_handle); + if (asm_index == -1) { + *error_code = ERR_ASM_POLICY_INVALID_HANDLE; + asm_error_r( "[Error] >>>> Can not find index from instance_id %ld, handle %d [%d]\n", + asm_rcv_msg.instance_id, asm_rcv_msg.data.cmd_handle, __LINE__); + return false; + } + + *error_code = ERR_ASM_POLICY_CANNOT_PLAY; + return false; + } else { + if (!__ASM_get_sound_state(&rcv_sound_status_value, error_code)) { + asm_error("[ASM_CB][Error = %d] asm_callback_handler : ASM_set_sound_state => __ASM_get_sound_state \n", *error_code); + } + + asm_info("[ASM_CB] asm_callback_handler : Callback : TID(%ld), handle(%d)\n", asm_rcv_msg.instance_id, asm_rcv_msg.data.cmd_handle); + + asm_index = __ASM_find_index(asm_rcv_msg.data.cmd_handle); + if (asm_index == -1) { + *error_code = ERR_ASM_POLICY_INVALID_HANDLE; + asm_error_r("[Error] >>>> Can not find index from instance_id %ld, handle %d [%d]\n", + asm_rcv_msg.instance_id, asm_rcv_msg.data.cmd_handle, __LINE__); + return false; + } + + if (ASM_sound_handle[asm_index].asm_callback!=NULL) { + ASM_sound_handle[asm_index].asm_callback(asm_rcv_msg.data.cmd_handle, ASM_sound_handle[asm_index].sound_event, asm_rcv_msg.data.result_sound_command, rcv_sound_status_value, ASM_sound_handle[asm_index].cb_data); + } else { + asm_info("[ASM_CB]callback in null\n"); + } + } + break; + + case ASM_COMMAND_PLAY: + case ASM_COMMAND_NONE: + case ASM_COMMAND_RESUME: + default: + break; + } + /********************************************************************************************************/ + asm_info(" <<<<<<<<<<<<<<<< [AFTER] Callback : Main Context >>>>>>>>>>>>>>>>>>>> \n"); + + } + + + asm_info(">>>> ASM_set_sound_state : Event(%s), State(%s) \n", ASM_sound_events_str[sound_event],ASM_sound_state_str[sound_state]); + + return true; +} + +EXPORT_API +void ASM_dump_sound_state() +{ + int error = 0; + int ret = 0; + + if (!__ASM_init_msg(&error) ) { + asm_error("[Error = %d] >>>> %s =>__asm_init \n", error, __func__); + } + if (!__asm_construct_snd_msg(getpid(), 0, 0, ASM_REQUEST_DUMP, ASM_STATE_NONE, ASM_RESOURCE_NONE, NULL)) { + asm_error_r("[Error] >>>> %s : Send msg construct failed.\n", __func__); + return; + } + NO_EINTR(ret = msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0)); + if (ret == -1) { + asm_error_r("[Error] >>>> ASM_dump_sound_state : Msgsnd failed (%d,%s) \n", errno, strerror(errno)); + return; + } +} + + +void ASM_ask_sound_policy(ASM_sound_events_t playing_sound, ASM_sound_events_t request_sound, + ASM_sound_cases_t *sound_policy) +{ +} + + +#if defined(CONFIG_ENABLE_SIGNAL_HANDLER) +struct sigaction ASM_int_old_action; +struct sigaction ASM_abrt_old_action; +struct sigaction ASM_segv_old_action; +struct sigaction ASM_term_old_action; +struct sigaction ASM_sys_old_action; +struct sigaction ASM_xcpu_old_action; + +void __ASM_unregister_sound(int index) +{ + int error_code = 0; + int ret = 0; + unsigned int sound_status_value; + + asm_info(" <<<< __ASM_unregister_sound : Event(%s), Index(%d) \n", ASM_sound_events_str[ASM_sound_handle[index].sound_event], index); + if (!__ASM_get_sound_state(&sound_status_value, &error_code)) { + asm_error("[Error = %d] >>>> ASM_unregister_sound => __ASM_get_sound_state \n", error_code); + } + if (!__ASM_set_sound_state(ASM_sound_handle[index].sound_event, ASM_STATE_NONE, &error_code)) { + asm_error("[Error = %d] >>>> __ASM_unregister_sound => __ASM_set_sound_state(NONE) \n", error_code); + } + + if (!__asm_construct_snd_msg(ASM_sound_handle[index].asm_tid, ASM_sound_handle[index].handle, ASM_sound_handle[index].sound_event, ASM_REQUEST_UNREGISTER, ASM_STATE_NONE, ASM_RESOURCE_NONE, &error_code)) { + asm_error(" >>>> Send msg construct failed.\n"); + } + + NO_EINTR(ret = msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0)); + if (ret == -1) { + asm_error_r("[Error] >>>> __ASM_unregister_sound : Msgsnd failed (%d,%s) \n", errno, strerror(errno)); + } + + __ASM_destroy_callback(index); + + asm_info(" >>>> __ASM_unregister_sound : Event(%s) \n", ASM_sound_events_str[ASM_sound_handle[index].sound_event]); + + ASM_sound_handle[index].asm_fd = 0; + ASM_sound_handle[index].asm_tid = 0; + ASM_sound_handle[index].sound_event = ASM_EVENT_NONE; + ASM_sound_handle[index].is_used = FALSE; + +} + + +void __ASM_signal_handler(int signo) +{ + int exit_pid = 0; + int asm_index = 0; + int run_emergency_exit = 0; + + for (asm_index=0 ;asm_index < ASM_HANDLE_MAX; asm_index++) { + if (ASM_sound_handle[asm_index].is_used == TRUE) { + exit_pid = ASM_sound_handle[asm_index].asm_tid; + if (exit_pid == asmgettid()) { + run_emergency_exit = 1; + break; + } + } + } + + if (run_emergency_exit) { + asm_snd_msg.instance_id = exit_pid; + asm_snd_msg.data.handle = 0; + asm_snd_msg.data.request_id = ASM_REQUEST_EMERGENT_EXIT; + asm_snd_msg.data.sound_event = 0; + asm_snd_msg.data.sound_state = 0; + /* signal block -------------- */ + sigset_t old_mask, all_mask; + sigfillset(&all_mask); + sigprocmask(SIG_BLOCK, &all_mask, &old_mask); + + if (msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0) < 0) { + asm_info("[signal handler][msgsnd failed]tid=%ld, reqid=%d, handle=0x%x, state=0x%x event=%d size=%d\n",asm_snd_msg.instance_id, + asm_snd_msg.data.request_id, asm_snd_msg.data.handle, asm_snd_msg.data.sound_state, asm_snd_msg.data.sound_event, sizeof(asm_snd_msg.data) ); + int tmpid = msgget((key_t)2014, 0666); + if (msgsnd(tmpid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0) > 0) { + asm_info("[signal handler]msgsnd succeed\n"); + } else { + asm_critical("[signal handler]msgsnd retry also failed.\n"); + } + } + + sigprocmask(SIG_SETMASK, &old_mask, NULL); + /* signal unblock ------------ */ + } + + switch (signo) { + case SIGINT: + sigaction(SIGINT, &ASM_int_old_action, NULL); + raise( signo); + break; + case SIGABRT: + sigaction(SIGABRT, &ASM_abrt_old_action, NULL); + raise( signo); + break; + case SIGSEGV: + sigaction(SIGSEGV, &ASM_segv_old_action, NULL); + raise( signo); + break; + case SIGTERM: + sigaction(SIGTERM, &ASM_term_old_action, NULL); + raise( signo); + break; + case SIGSYS: + sigaction(SIGSYS, &ASM_sys_old_action, NULL); + raise( signo); + break; + case SIGXCPU: + sigaction(SIGXCPU, &ASM_xcpu_old_action, NULL); + raise( signo); + break; + default: + break; + } +} + +#endif +void __attribute__((constructor)) __ASM_init_module(void) +{ +#if defined(CONFIG_ENABLE_SIGNAL_HANDLER) + struct sigaction ASM_action; + ASM_action.sa_handler = __ASM_signal_handler; + ASM_action.sa_flags = SA_NOCLDSTOP; + sigemptyset(&ASM_action.sa_mask); + + asm_info(" __ASM_init_module : start \n"); + + sigaction(SIGINT, &ASM_action, &ASM_int_old_action); + sigaction(SIGABRT, &ASM_action, &ASM_abrt_old_action); + sigaction(SIGSEGV, &ASM_action, &ASM_segv_old_action); + sigaction(SIGTERM, &ASM_action, &ASM_term_old_action); + sigaction(SIGSYS, &ASM_action, &ASM_sys_old_action); + sigaction(SIGXCPU, &ASM_action, &ASM_xcpu_old_action); +#endif +} + + +void __attribute__((destructor)) __ASM_fini_module(void) +{ +#if defined(CONFIG_ENABLE_SIGNAL_HANDLER) + asm_info(" __ASM_fini_module : start \n"); + + int exit_pid = 0; + int asm_index = 0; + int run_emergency_exit = 0; + + for (asm_index = 0; asm_index < ASM_HANDLE_MAX; asm_index++) { + if (ASM_sound_handle[asm_index].is_used == TRUE) { + exit_pid = ASM_sound_handle[asm_index].asm_tid; + if (exit_pid == asmgettid()) { + run_emergency_exit = 1; + break; + } + } + } + + if (run_emergency_exit) { + asm_snd_msg.instance_id = exit_pid; + asm_snd_msg.data.handle = 0; /* dummy */ + asm_snd_msg.data.request_id = ASM_REQUEST_EMERGENT_EXIT; + asm_snd_msg.data.sound_event = 0; + asm_snd_msg.data.sound_state = 0; + + if (msgsnd(asm_snd_msgid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0) < 0 ) { + asm_info( "[signal handler][msgsnd failed]tid=%ld, reqid=%d, handle=0x%x, state=0x%x event=%d size=%d\n",asm_snd_msg.instance_id, + asm_snd_msg.data.request_id, asm_snd_msg.data.handle, asm_snd_msg.data.sound_state, asm_snd_msg.data.sound_event, sizeof(asm_snd_msg.data) ); + int tmpid = msgget((key_t)2014, 0666); + if (msgsnd(tmpid, (void *)&asm_snd_msg, sizeof(asm_snd_msg.data), 0) > 0) { + asm_info("[signal handler]msgsnd succeed\n"); + } else { + asm_critical("[signal handler]msgsnd retry also failed.\n"); + } + } + } +#endif + sigaction(SIGINT, &ASM_int_old_action, NULL); + sigaction(SIGABRT, &ASM_abrt_old_action, NULL); + sigaction(SIGSEGV, &ASM_segv_old_action, NULL); + sigaction(SIGTERM, &ASM_term_old_action, NULL); + sigaction(SIGSYS, &ASM_sys_old_action, NULL); + sigaction(SIGXCPU, &ASM_xcpu_old_action, NULL); +} + |