4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Seungbae Shin <seungbae.shin@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
25 #include <sys/types.h>
28 #include <mm_session_private.h>
32 #include <audio-session-manager.h>
36 #define EXPORT_API __attribute__((__visibility__("default")))
37 #define MAX_FILE_LENGTH 256
39 #define TRY_LOCK(x, x_ret) \
41 x_ret = pthread_mutex_trylock(&(x));\
43 debug_warning("Mutex trylock failed, (0x%x)",x_ret);\
48 if(pthread_mutex_lock(&(x)) != 0) {\
49 debug_error("Mutex lock error");\
54 if(pthread_mutex_unlock(&(x)) != 0) {\
55 debug_error("Mutex unlock error");\
60 if(pthread_mutex_destroy(&(x)) != 0) {\
61 debug_error("Mutex destroy error");\
66 session_callback_fn fn;
69 session_event_t event;
72 int g_call_asm_handle = -1;
73 int g_monitor_asm_handle = -1;
74 session_monitor_t g_monitor_data;
76 pthread_mutex_t g_mutex_monitor = PTHREAD_MUTEX_INITIALIZER;
78 ASM_cb_result_t asm_monitor_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data);
81 int mm_session_init(int sessiontype)
84 return mm_session_init_ex(sessiontype, NULL, NULL);
89 int mm_session_init_ex(int sessiontype, session_callback_fn callback, void* user_param)
92 int result = MM_ERROR_NONE;
94 pthread_mutex_init(&g_mutex_monitor, NULL);
96 debug_log("type : %d", sessiontype);
98 if(sessiontype < MM_SESSION_TYPE_SHARE || sessiontype >= MM_SESSION_PRIVATE_TYPE_NUM) {
99 debug_error("Invalid argument %d",sessiontype);
100 return MM_ERROR_INVALID_ARGUMENT;
103 result = _mm_session_util_read_type(-1, <ype);
104 if(MM_ERROR_INVALID_HANDLE != result) {
105 debug_error("Session already initialized. Please finish current session first");
106 return MM_ERROR_POLICY_DUPLICATED;
109 /* Monitor Callback */
110 if(NULL == callback) {
111 debug_warning("Null callback function");
113 g_monitor_data.fn = callback;
114 g_monitor_data.data = user_param;
115 LOCK(g_mutex_monitor);
116 if(!ASM_register_sound(-1, &g_monitor_asm_handle, ASM_EVENT_MONITOR, ASM_STATE_NONE, asm_monitor_callback, (void*)&g_monitor_data, ASM_RESOURCE_NONE, &error)) {
117 debug_error("Can not register monitor");
118 UNLOCK(g_mutex_monitor);
119 return MM_ERROR_INVALID_HANDLE;
121 UNLOCK(g_mutex_monitor);
124 /* Register here for call session types */
125 if(sessiontype == MM_SESSION_TYPE_CALL) {
126 if(!ASM_register_sound(-1, &g_call_asm_handle, ASM_EVENT_CALL, ASM_STATE_PLAYING, NULL, NULL, ASM_RESOURCE_NONE, &error)) {
127 debug_error("Can not register sound");
128 return MM_ERROR_INVALID_HANDLE;
130 } else if(sessiontype == MM_SESSION_TYPE_VIDEOCALL) {
131 if(!ASM_register_sound(-1, &g_call_asm_handle, ASM_EVENT_VIDEOCALL, ASM_STATE_PLAYING, NULL, NULL, ASM_RESOURCE_CAMERA|ASM_RESOURCE_VIDEO_OVERLAY, &error)) {
132 debug_error("Can not register sound");
133 return MM_ERROR_INVALID_HANDLE;
135 } else if(sessiontype == MM_SESSION_TYPE_RICH_CALL) {
136 if(!ASM_register_sound(-1, &g_call_asm_handle, ASM_EVENT_RICH_CALL, ASM_STATE_PLAYING, NULL, NULL, ASM_RESOURCE_NONE, &error)) {
137 debug_error("Can not register sound");
138 return MM_ERROR_INVALID_HANDLE;
142 result = _mm_session_util_write_type(-1, sessiontype);
143 if(MM_ERROR_NONE != result) {
144 debug_error("Write type failed");
145 if(sessiontype == MM_SESSION_TYPE_CALL) {
146 ASM_unregister_sound(g_call_asm_handle, ASM_EVENT_CALL, &error);
147 } else if(sessiontype == MM_SESSION_TYPE_VIDEOCALL) {
148 ASM_unregister_sound(g_call_asm_handle, ASM_EVENT_VIDEOCALL, &error);
149 } else if(sessiontype == MM_SESSION_TYPE_RICH_CALL) {
150 ASM_unregister_sound(g_call_asm_handle, ASM_EVENT_RICH_CALL, &error);
152 LOCK(g_mutex_monitor);
153 ASM_unregister_sound(g_monitor_asm_handle, ASM_EVENT_MONITOR, &error);
154 UNLOCK(g_mutex_monitor);
161 return MM_ERROR_NONE;
165 int mm_session_get_current_type (int *sessiontype)
167 int result = MM_ERROR_NONE;
170 if (sessiontype == NULL) {
171 debug_error("input argument is NULL\n");
172 return MM_ERROR_INVALID_ARGUMENT;
175 result = _mm_session_util_read_type(-1, <ype);
176 if(result == MM_ERROR_NONE) {
177 debug_log("Current process session type = [%d]\n", ltype);
178 *sessiontype = ltype;
180 debug_error("failed to get current process session type!!\n");
187 int mm_session_finish()
190 int result = MM_ERROR_NONE;
191 int sessiontype = MM_SESSION_TYPE_SHARE;
192 ASM_sound_states_t state = ASM_STATE_NONE;
196 result = _mm_session_util_read_type(-1, &sessiontype);
197 if(MM_ERROR_NONE != result) {
198 debug_error("Can not read current type");
199 DESTROY(g_mutex_monitor);
203 /* Unregister call session here */
204 if(sessiontype == MM_SESSION_TYPE_CALL) {
205 if(!ASM_unregister_sound(g_call_asm_handle, ASM_EVENT_CALL, &error)) {
206 debug_error("\"CALL\" ASM unregister failed");
209 g_call_asm_handle = -1;
210 } else if(sessiontype == MM_SESSION_TYPE_VIDEOCALL) {
211 if(!ASM_unregister_sound(g_call_asm_handle, ASM_EVENT_VIDEOCALL, &error)) {
212 debug_error("\"VIDEOCALL\" ASM unregister failed");
215 g_call_asm_handle = -1;
216 } else if(sessiontype == MM_SESSION_TYPE_RICH_CALL) {
217 if(!ASM_unregister_sound(g_call_asm_handle, ASM_EVENT_RICH_CALL, &error)) {
218 debug_error("\"RICH-CALL\" ASM unregister failed");
221 g_call_asm_handle = -1;
224 /* Check monitor handle */
225 TRY_LOCK(g_mutex_monitor, error);
227 if(g_monitor_asm_handle != -1) {
228 if(!ASM_get_process_session_state(g_monitor_asm_handle, &state, &error)) {
229 debug_error("[%s] Can not get process status", __func__);
230 UNLOCK(g_mutex_monitor);
231 DESTROY(g_mutex_monitor);
232 return MM_ERROR_POLICY_INTERNAL;
235 case ASM_STATE_IGNORE:
238 case ASM_STATE_PLAYING:
239 case ASM_STATE_WAITING:
241 case ASM_STATE_PAUSE:
242 case ASM_STATE_PAUSE_BY_APP:
243 debug_error("[%s] MSL instance still alive", __func__);
244 UNLOCK(g_mutex_monitor);
245 DESTROY(g_mutex_monitor);
246 return MM_ERROR_POLICY_BLOCKED;
249 /* Unregister monitor */
250 if(!ASM_unregister_sound(g_monitor_asm_handle, ASM_EVENT_MONITOR, &error)) {
251 debug_error("ASM unregister monitor failed");
252 UNLOCK(g_mutex_monitor);
255 debug_log("ASM unregister monitor success");
256 g_monitor_asm_handle = -1;
259 UNLOCK(g_mutex_monitor);
260 DESTROY(g_mutex_monitor);
263 result = _mm_session_util_delete_type(-1);
264 if(result != MM_ERROR_NONE)
269 return MM_ERROR_NONE;
272 DESTROY(g_mutex_monitor);
273 return MM_ERROR_INVALID_HANDLE;
277 int mm_session_set_subsession (mm_subsession_t subsession)
280 int result = MM_ERROR_NONE;
284 if(g_call_asm_handle == -1) {
285 debug_error ("call session is not started...\n");
286 return MM_ERROR_INVALID_HANDLE;
289 /* FIXME : Error handling */
290 ASM_set_subsession (g_call_asm_handle, subsession, &error, NULL);
294 return MM_ERROR_NONE;
298 int mm_session_get_subsession (mm_subsession_t *subsession)
301 int result = MM_ERROR_NONE;
304 if(g_call_asm_handle == -1) {
305 debug_error ("call session is not started...\n");
306 return MM_ERROR_INVALID_HANDLE;
309 ASM_get_subsession (g_call_asm_handle, subsession, &error, NULL);
311 debug_log("ASM_get_subsession returned [%d]\n", *subsession);
314 return MM_ERROR_NONE;
318 int _mm_session_util_delete_type(int app_pid)
321 char filename[MAX_FILE_LENGTH];
326 mypid = (pid_t)app_pid;
328 ////// DELETE SESSION TYPE /////////
329 snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d",mypid);
330 if(-1 == unlink(filename))
331 return MM_ERROR_FILE_NOT_FOUND;
332 ////// DELETE SESSION TYPE /////////
334 return MM_ERROR_NONE;
338 int _mm_session_util_write_type(int app_pid, int sessiontype)
342 char filename[MAX_FILE_LENGTH];
344 if(sessiontype < MM_SESSION_TYPE_SHARE || sessiontype >= MM_SESSION_PRIVATE_TYPE_NUM) {
345 return MM_ERROR_INVALID_ARGUMENT;
351 mypid = (pid_t)app_pid;
353 ////// WRITE SESSION TYPE /////////
354 snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d",mypid);
355 fd = open(filename, O_WRONLY | O_CREAT, 0644 );
357 debug_error("open() failed with %d",errno);
358 return MM_ERROR_FILE_WRITE;
360 write(fd, &sessiontype, sizeof(int));
361 if(0 > fchmod (fd, 00777)) {
362 debug_log("fchmod failed with %d", errno);
365 ////// WRITE SESSION TYPE /////////
367 return MM_ERROR_NONE;
371 int _mm_session_util_read_type(int app_pid, int *sessiontype)
375 char filename[MAX_FILE_LENGTH];
377 if(sessiontype == NULL)
378 return MM_ERROR_INVALID_ARGUMENT;
383 mypid = (pid_t)app_pid;
385 ////// READ SESSION TYPE /////////
386 snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d",mypid);
387 fd = open(filename, O_RDONLY);
389 return MM_ERROR_INVALID_HANDLE;
391 read(fd, sessiontype, sizeof(int));
393 ////// READ SESSION TYPE /////////
395 return MM_ERROR_NONE;
398 gboolean _asm_monitor_cb(gpointer *data)
400 session_monitor_t* monitor = (session_monitor_t*)data;
403 debug_log("calling _asm_monitor_cb()");
404 monitor->fn(monitor->msg, monitor->event, monitor->data);
411 static session_event_t _translate_from_asm_to_mm_session (ASM_event_sources_t event_src)
415 case ASM_EVENT_SOURCE_CALL_START:
416 return MM_SESSION_EVENT_CALL;
418 case ASM_EVENT_SOURCE_EARJACK_UNPLUG:
419 return MM_SESSION_EVENT_EARJACK_UNPLUG;
421 case ASM_EVENT_SOURCE_RESOURCE_CONFLICT:
422 return MM_SESSION_EVENT_RESOURCE_CONFLICT;
424 case ASM_EVENT_SOURCE_ALARM_START:
425 case ASM_EVENT_SOURCE_ALARM_END:
426 return MM_SESSION_EVENT_ALARM;
428 case ASM_EVENT_SOURCE_EMERGENCY_START:
429 case ASM_EVENT_SOURCE_EMERGENCY_END:
430 return MM_SESSION_EVENT_EMERGENCY;
432 case ASM_EVENT_SOURCE_RESUMABLE_MEDIA:
433 return MM_SESSION_EVENT_RESUMABLE_MEDIA;
435 case ASM_EVENT_SOURCE_MEDIA:
437 return MM_SESSION_EVENT_MEDIA;
442 asm_monitor_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
444 ASM_cb_result_t cb_res = ASM_CB_RES_NONE;
445 session_monitor_t *monitor = (session_monitor_t*)cb_data;
447 debug_log("monitor callback called for handle %d, event_src %d", handle, event_src);
449 debug_log("monitor instance is null\n");
450 return ASM_CB_RES_IGNORE;
455 case ASM_COMMAND_STOP:
456 case ASM_COMMAND_PAUSE:
457 //call session_callback_fn for stop here
459 monitor->msg = MM_SESSION_MSG_STOP;
460 monitor->event = _translate_from_asm_to_mm_session (event_src);
461 g_idle_add((GSourceFunc)_asm_monitor_cb, (gpointer)monitor);
463 cb_res = (command == ASM_COMMAND_STOP)? ASM_CB_RES_STOP : ASM_CB_RES_PAUSE;
466 case ASM_COMMAND_RESUME:
467 case ASM_COMMAND_PLAY:
468 //call session_callback_fn for resume here
470 monitor->msg = MM_SESSION_MSG_RESUME;
471 monitor->event = _translate_from_asm_to_mm_session (event_src);
472 g_idle_add((GSourceFunc)_asm_monitor_cb, (gpointer)monitor);
474 cb_res = ASM_CB_RES_IGNORE;
483 __attribute__ ((destructor))
484 void __mmsession_finalize(void)
490 TRY_LOCK(g_mutex_monitor, error);
492 if(g_monitor_asm_handle != -1) {
493 /* Unregister monitor */
494 if(!ASM_unregister_sound(g_monitor_asm_handle, ASM_EVENT_MONITOR, &error)) {
495 debug_error("ASM unregister monitor failed");
497 debug_log("ASM unregister monitor success");
498 g_monitor_asm_handle = -1;
501 UNLOCK(g_mutex_monitor);
502 DESTROY(g_mutex_monitor);
504 _mm_session_util_delete_type(-1);
509 __attribute__ ((constructor))
510 void __mmsession_initialize(void)