disable signal handler for VD dotnet application, cleanup will be done by external...
[platform/core/multimedia/libmm-session.git] / mm_session.c
1 /*
2  * libmm-session
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin at samsung.com>, Sangchul Lee <sc11.lee at samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <mm_session_private.h>
28 #include <mm_error.h>
29 #include <mm_debug.h>
30 #include <errno.h>
31 #include <pthread.h>
32 #include <signal.h>
33 #include <stdlib.h>
34
35 #define EXPORT_API __attribute__((__visibility__("default")))
36 #define MAX_FILE_LENGTH 256
37
38 int g_session_type = -1;
39
40 struct sigaction session_int_old_action;
41 struct sigaction session_abrt_old_action;
42 struct sigaction session_segv_old_action;
43 struct sigaction session_term_old_action;
44 struct sigaction session_sys_old_action;
45 struct sigaction session_xcpu_old_action;
46
47 EXPORT_API
48 int mm_session_init(int sessiontype)
49 {
50         int result = MM_ERROR_NONE;
51         int ltype = 0;
52         bool do_not_update_session_info = false;
53
54         debug_fenter();
55         debug_log("type : %d", sessiontype);
56
57         if (sessiontype < MM_SESSION_TYPE_MEDIA || sessiontype >= MM_SESSION_TYPE_NUM) {
58                 debug_error("Invalid argument %d", sessiontype);
59                 return MM_ERROR_INVALID_ARGUMENT;
60         }
61
62         result = _mm_session_util_read_type(-1, &ltype);
63         if (MM_ERROR_INVALID_HANDLE != result) {
64                 if ((ltype == MM_SESSION_TYPE_MEDIA_RECORD) && sessiontype == MM_SESSION_TYPE_MEDIA) {
65                         /* already set by mm-camcorder, mm-sound(pcm in), keep going */
66                         do_not_update_session_info = true;
67                 } else {
68                         debug_error("Session already initialized. Please finish current session first");
69                         return MM_ERROR_POLICY_DUPLICATED;
70                 }
71         }
72
73         g_session_type = sessiontype;
74
75         if (!do_not_update_session_info) {
76                 result = _mm_session_util_write_type(-1, sessiontype);
77                 if (MM_ERROR_NONE != result) {
78                         debug_error("Write type failed");
79                         g_session_type = -1;
80                         return result;
81                 }
82         }
83
84         debug_fleave();
85
86         return MM_ERROR_NONE;
87 }
88
89 EXPORT_API
90 int mm_session_update_option(session_update_type_t update_type, int options)
91 {
92         int result = MM_ERROR_NONE;
93         int ltype = 0;
94         int loption = 0;
95
96         debug_log("update_type: %d(0:Add, 1:Remove), options: %x", update_type, options);
97
98         if (update_type < 0 || update_type >= MM_SESSION_UPDATE_TYPE_NUM) {
99                 debug_error("Invalid update_type value(%d)", update_type);
100                 return MM_ERROR_INVALID_ARGUMENT;
101         }
102         if (options < 0) {
103                 debug_error("Invalid options value(%x)", options);
104                 return MM_ERROR_INVALID_ARGUMENT;
105         }
106
107         result = _mm_session_util_read_information(-1, &ltype, &loption);
108         if (result) {
109                 debug_error("failed to _mm_session_util_read_information(), ret(%x)", result);
110                 return result;
111         }
112         debug_log("[current] session_type: %d, session_option: %x", ltype, loption);
113
114         if (update_type == MM_SESSION_UPDATE_TYPE_ADD)
115                 loption |= options;
116         else if (update_type == MM_SESSION_UPDATE_TYPE_REMOVE)
117                 loption &= ~options;
118
119         result = _mm_session_util_write_information(-1, ltype, loption);
120         if (result) {
121                 debug_error("failed to _mm_session_util_write_information(), ret(%x)", result);
122                 return result;
123         }
124
125         debug_log("[updated] session_type: %d, session_option: %x", ltype, loption);
126
127
128         return MM_ERROR_NONE;
129 }
130
131 EXPORT_API
132 int mm_session_get_current_type(int *sessiontype)
133 {
134         int result = MM_ERROR_NONE;
135         int ltype = 0;
136
137         debug_fenter();
138
139         if (sessiontype == NULL) {
140                 debug_error("input argument is NULL\n");
141                 return MM_ERROR_INVALID_ARGUMENT;
142         }
143
144         result = _mm_session_util_read_type(-1, &ltype);
145         if (result == MM_ERROR_NONE) {
146                 debug_log("Current process session type = [%d]\n", ltype);
147                 *sessiontype = ltype;
148         } else {
149                 debug_error("failed to get current process session type!!\n");
150         }
151
152         debug_fleave();
153
154         return result;
155 }
156
157 EXPORT_API
158 int mm_session_get_current_information(int *session_type, int *session_options)
159 {
160         int result = MM_ERROR_NONE;
161         int ltype = 0;
162         int loption = 0;
163
164         debug_fenter();
165
166         if (session_type == NULL) {
167                 debug_error("input argument is NULL\n");
168                 return MM_ERROR_INVALID_ARGUMENT;
169         }
170
171         result = _mm_session_util_read_information(-1, &ltype, &loption);
172         if (result == MM_ERROR_NONE) {
173                 debug_log("Current process session type = [%d], options = [%x]\n", ltype, loption);
174                 *session_type = ltype;
175                 *session_options = loption;
176         } else {
177                 debug_error("failed to get current process session type, option!!\n");
178         }
179
180         debug_fleave();
181
182         return result;
183 }
184
185 EXPORT_API
186 int mm_session_finish(void)
187 {
188         int result = MM_ERROR_NONE;
189         int sessiontype = MM_SESSION_TYPE_MEDIA;
190
191         debug_fenter();
192
193         result = _mm_session_util_read_type(-1, &sessiontype);
194         if (MM_ERROR_NONE != result) {
195                 debug_error("Can not read current type");
196                 return result;
197         }
198
199         /* Check monitor handle */
200         result = _mm_session_util_delete_information(-1);
201         if (result != MM_ERROR_NONE)
202                 return result;
203
204         debug_fleave();
205
206         return MM_ERROR_NONE;
207 }
208
209 EXPORT_API
210 int _mm_session_util_delete_information(int app_pid)
211 {
212         pid_t mypid;
213         char filename[MAX_FILE_LENGTH];
214
215         if (app_pid == -1)
216                 mypid = getpid();
217         else
218                 mypid = (pid_t)app_pid;
219
220         ////// DELETE SESSION TYPE /////////
221         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
222         if (-1 ==  unlink(filename))
223                 return MM_ERROR_FILE_NOT_FOUND;
224         ////// DELETE SESSION TYPE /////////
225
226         return MM_ERROR_NONE;
227 }
228
229 EXPORT_API
230 int _mm_session_util_write_type(int app_pid, int sessiontype)
231 {
232         pid_t mypid;
233         int fd = -1;
234         char filename[MAX_FILE_LENGTH];
235
236         if (sessiontype < MM_SESSION_TYPE_MEDIA || sessiontype >= MM_SESSION_TYPE_NUM)
237                 return MM_ERROR_INVALID_ARGUMENT;
238
239         if (app_pid == -1)
240                 mypid = getpid();
241         else
242                 mypid = (pid_t)app_pid;
243
244         ////// WRITE SESSION TYPE /////////
245         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
246         fd = open(filename, O_WRONLY | O_CREAT, 0644);
247         if (fd < 0) {
248                 debug_error("open() failed with %d", errno);
249                 return MM_ERROR_FILE_WRITE;
250         }
251         sessiontype = sessiontype << 16;
252         write(fd, &sessiontype, sizeof(int));
253         if (0 > fchmod(fd, 00777))
254                 debug_error("fchmod failed with %d", errno);
255         else
256                 debug_warning("write sessiontype(%d) to /tmp/mm_session_%d", sessiontype >> 16, mypid);
257
258         close(fd);
259         ////// WRITE SESSION TYPE /////////
260
261         return MM_ERROR_NONE;
262 }
263
264 EXPORT_API
265 int _mm_session_util_read_type(int app_pid, int *sessiontype)
266 {
267         pid_t mypid;
268         int fd = -1;
269         char filename[MAX_FILE_LENGTH];
270         int result = MM_ERROR_NONE;
271
272         debug_fenter();
273
274         if (sessiontype == NULL)
275                 return MM_ERROR_INVALID_ARGUMENT;
276
277         if (app_pid == -1)
278                 mypid = getpid();
279         else
280                 mypid = (pid_t)app_pid;
281
282         ////// READ SESSION TYPE /////////
283         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
284         fd = open(filename, O_RDONLY);
285         if (fd < 0)
286                 return MM_ERROR_INVALID_HANDLE;
287
288         if (read(fd, sessiontype, sizeof(int)) == sizeof(int)) {
289                 *sessiontype = *sessiontype >> 16;
290                 debug_warning("read sessiontype(%d) from /tmp/mm_session_%d", *sessiontype, mypid);
291         } else {
292                 debug_error("failed to read from %s, errno %d", filename, errno);
293                 result = MM_ERROR_INVALID_HANDLE;
294         }
295
296         close(fd);
297         ////// READ SESSION TYPE /////////
298
299         debug_fleave();
300
301         return result;
302 }
303
304 EXPORT_API
305 int _mm_session_util_write_information(int app_pid, int session_type, int flags)
306 {
307         pid_t mypid;
308         int fd = -1;
309         char filename[MAX_FILE_LENGTH];
310         int result_info = 0;
311
312         if ((session_type != MM_SESSION_TYPE_REPLACED_BY_STREAM) &&
313             (session_type < MM_SESSION_TYPE_MEDIA || session_type >= MM_SESSION_TYPE_NUM)) {
314                 return MM_ERROR_INVALID_ARGUMENT;
315         }
316         if (flags < 0)
317                 return MM_ERROR_INVALID_ARGUMENT;
318
319         if (app_pid == -1)
320                 mypid = getpid();
321         else
322                 mypid = (pid_t)app_pid;
323
324         ////// WRITE SESSION INFO /////////
325         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
326         fd = open(filename, O_WRONLY | O_CREAT, 0644);
327         if (fd < 0) {
328                 debug_error("open() failed with %d", errno);
329                 return MM_ERROR_FILE_WRITE;
330         }
331
332         result_info = (flags) | (session_type << 16);
333         write(fd, &result_info, sizeof(int));
334         if (0 > fchmod(fd, 00777))
335                 debug_error("fchmod failed with %d", errno);
336         else
337                 debug_warning("write session information(%x) to /tmp/mm_session_%d", result_info, mypid);
338         close(fd);
339         ////// WRITE SESSION INFO /////////
340
341         return MM_ERROR_NONE;
342 }
343
344 EXPORT_API
345 int _mm_session_util_read_information(int app_pid, int *session_type, int *flags)
346 {
347         pid_t mypid;
348         int fd = -1;
349         char filename[MAX_FILE_LENGTH];
350         int result_info = 0;
351         int result = MM_ERROR_NONE;
352
353         debug_fenter();
354
355         if (session_type == NULL || flags == NULL)
356                 return MM_ERROR_INVALID_ARGUMENT;
357
358         if (app_pid == -1)
359                 mypid = getpid();
360         else
361                 mypid = (pid_t)app_pid;
362
363         ////// READ SESSION INFO /////////
364         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
365         fd = open(filename, O_RDONLY);
366         if (fd < 0)
367                 return MM_ERROR_INVALID_HANDLE;
368         if (read(fd, &result_info, sizeof(int)) == sizeof(int)) {
369                 *session_type = result_info >> 16;
370                 *flags = result_info & 0x0000ffff;
371                 debug_warning("read session_type(%d), session_option(%x) from /tmp/mm_session_%d", *session_type, *flags, mypid);
372         } else {
373                 debug_error("failed to read from %s, errno %d", filename, errno);
374                 result = MM_ERROR_INVALID_HANDLE;
375         }
376
377         close(fd);
378         ////// READ SESSION INFO /////////
379
380         debug_fleave();
381
382         return result;
383 }
384
385 void __session_signal_handler(int signo, siginfo_t *siginfo, void *context)
386 {
387         sigset_t old_mask, all_mask;
388
389         debug_warning("ENTER, signo(%d), siginfo(%p), context(%p)", signo, siginfo, context);
390
391         /* signal block -------------- */
392         sigfillset(&all_mask);
393         sigprocmask(SIG_BLOCK, &all_mask, &old_mask);
394
395         _mm_session_util_delete_information(-1);
396
397         sigprocmask(SIG_SETMASK, &old_mask, NULL);
398         /* signal unblock ------------ */
399
400         switch (signo) {
401         case SIGINT:
402                 if (session_int_old_action.sa_sigaction)
403                         session_int_old_action.sa_sigaction(signo, siginfo, context);
404                 else
405                         sigaction(signo, &session_int_old_action, NULL);
406                 break;
407         case SIGABRT:
408                 if (session_abrt_old_action.sa_sigaction)
409                         session_abrt_old_action.sa_sigaction(signo, siginfo, context);
410                 else
411                         sigaction(signo, &session_abrt_old_action, NULL);
412                 break;
413         case SIGSEGV:
414                 if (session_segv_old_action.sa_sigaction)
415                         session_segv_old_action.sa_sigaction(signo, siginfo, context);
416                 else
417                         sigaction(signo, &session_segv_old_action, NULL);
418                 break;
419         case SIGTERM:
420                 if (session_term_old_action.sa_sigaction)
421                         session_term_old_action.sa_sigaction(signo, siginfo, context);
422                 else
423                         sigaction(signo, &session_term_old_action, NULL);
424                 break;
425         case SIGSYS:
426                 if (session_sys_old_action.sa_sigaction)
427                         session_sys_old_action.sa_sigaction(signo, siginfo, context);
428                 else
429                         sigaction(signo, &session_sys_old_action, NULL);
430                 break;
431         case SIGXCPU:
432                 if (session_xcpu_old_action.sa_sigaction)
433                         session_xcpu_old_action.sa_sigaction(signo, siginfo, context);
434                 else
435                         sigaction(signo, &session_xcpu_old_action, NULL);
436                 break;
437         default:
438                 break;
439         }
440
441         debug_warning("LEAVE");
442 }
443
444 #ifdef TIZEN_TV
445 EXPORT_API
446 void mm_session_dotnet_cleanup(int signo)
447 {
448         debug_warning("dotnet cleanup [%d]", signo);
449         _mm_session_util_delete_information(-1);
450
451 }
452 static bool _is_dotnet_app(void)
453 {
454         char *is_dotnet = NULL;
455
456         is_dotnet = getenv("DOTNET_APP");
457         if (is_dotnet && atoi(is_dotnet) == 1)
458                 return true;
459         else
460                 return false;
461 }
462 #endif
463
464 __attribute__ ((constructor))
465 void __mmsession_initialize(void)
466 {
467         struct sigaction session_action;
468
469         debug_fenter();
470
471 #ifdef TIZEN_TV
472         if (_is_dotnet_app()) {
473                 debug_warning("no signal handler for dotnet!!");
474                 return;
475         }
476 #endif
477         session_action.sa_sigaction = __session_signal_handler;
478         session_action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
479
480         sigemptyset(&session_action.sa_mask);
481
482         sigaction(SIGINT, &session_action, &session_int_old_action);
483         sigaction(SIGABRT, &session_action, &session_abrt_old_action);
484         sigaction(SIGSEGV, &session_action, &session_segv_old_action);
485         sigaction(SIGTERM, &session_action, &session_term_old_action);
486         sigaction(SIGSYS, &session_action, &session_sys_old_action);
487         sigaction(SIGXCPU, &session_action, &session_xcpu_old_action);
488
489         debug_fleave();
490 }
491
492 __attribute__ ((destructor))
493 void __mmsession_finalize(void)
494 {
495
496         debug_fenter();
497
498         _mm_session_util_delete_information(-1);
499 #ifdef TIZEN_TV
500         if (_is_dotnet_app()) {
501                 debug_warning("no signal handler for dotnet!!");
502                 return;
503         }
504 #endif
505         sigaction(SIGINT, &session_int_old_action, NULL);
506         sigaction(SIGABRT, &session_abrt_old_action, NULL);
507         sigaction(SIGSEGV, &session_segv_old_action, NULL);
508         sigaction(SIGTERM, &session_term_old_action, NULL);
509         sigaction(SIGSYS, &session_sys_old_action, NULL);
510         sigaction(SIGXCPU, &session_xcpu_old_action, NULL);
511
512         debug_fleave();
513 }
514