6efb5a7d56039301b346dd143a274501b1611d2a
[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 <glib.h>
32 #include <pthread.h>
33 #include <signal.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         debug_fenter();
51         return mm_session_init_ex(sessiontype, NULL, NULL);
52         debug_fleave();
53 }
54
55 EXPORT_API
56 int mm_session_init_ex(int sessiontype, session_callback_fn callback, void* user_param)
57 {
58         int result = MM_ERROR_NONE;
59         int ltype = 0;
60         bool do_not_update_session_info = false;
61
62         debug_fenter();
63         debug_log("type : %d", sessiontype);
64
65         if (sessiontype < MM_SESSION_TYPE_MEDIA || sessiontype >= MM_SESSION_TYPE_NUM) {
66                 debug_error("Invalid argument %d",sessiontype);
67                 return MM_ERROR_INVALID_ARGUMENT;
68         }
69
70         result = _mm_session_util_read_type(-1, &ltype);
71         if (MM_ERROR_INVALID_HANDLE != result) {
72                 if ((ltype == MM_SESSION_TYPE_MEDIA_RECORD) && sessiontype == MM_SESSION_TYPE_MEDIA) {
73                         /* already set by mm-camcorder, mm-sound(pcm in), keep going */
74                         do_not_update_session_info = true;
75                 } else {
76                         debug_error("Session already initialized. Please finish current session first");
77                         return MM_ERROR_POLICY_DUPLICATED;
78                 }
79         }
80
81         /* Monitor Callback */
82         if (NULL == callback) {
83                 debug_warning("Null callback function");
84         } else {
85                 debug_warning("It was deprecated, do not use monitor callback, callback(%p), user_param(%p)", callback, user_param);
86         }
87
88         g_session_type = sessiontype;
89
90         if (!do_not_update_session_info) {
91                 result = _mm_session_util_write_type(-1, sessiontype);
92                 if (MM_ERROR_NONE != result) {
93                         debug_error("Write type failed");
94                         g_session_type = -1;
95                         return result;
96                 }
97         }
98
99         debug_fleave();
100
101         return MM_ERROR_NONE;
102 }
103
104 EXPORT_API
105 int mm_session_update_option(session_update_type_t update_type, int options)
106 {
107         int result = MM_ERROR_NONE;
108         int ltype = 0;
109         int loption = 0;
110
111         debug_log("update_type: %d(0:Add, 1:Remove), options: %x", update_type, options);
112
113         if (update_type < 0 || update_type >= MM_SESSION_UPDATE_TYPE_NUM) {
114                 debug_error("Invalid update_type value(%d)", update_type);
115                 return MM_ERROR_INVALID_ARGUMENT;
116         }
117         if (options < 0) {
118                 debug_error("Invalid options value(%x)", options);
119                 return MM_ERROR_INVALID_ARGUMENT;
120         }
121
122         result = _mm_session_util_read_information(-1, &ltype, &loption);
123         if (result) {
124                 debug_error("failed to _mm_session_util_read_information(), ret(%x)", result);
125                 return result;
126         }
127         debug_log("[current] session_type: %d, session_option: %x", ltype, loption);
128
129         if (update_type == MM_SESSION_UPDATE_TYPE_ADD) {
130                 loption |= options;
131         } else if (update_type == MM_SESSION_UPDATE_TYPE_REMOVE) {
132                 loption &= ~options;
133         }
134
135         result = _mm_session_util_write_information(-1, ltype, loption);
136         if (result) {
137                 debug_error("failed to _mm_session_util_write_information(), ret(%x)", result);
138                 return result;
139         }
140
141         debug_log("[updated] session_type: %d, session_option: %x", ltype, loption);
142
143
144         return MM_ERROR_NONE;
145 }
146
147 EXPORT_API
148 int mm_session_add_watch_callback(int watchevent, int watchstate, watch_callback_fn callback, void* user_param)
149 {
150         debug_fenter();
151
152         debug_fleave();
153
154         return MM_ERROR_NOT_SUPPORT_API;
155 }
156
157 EXPORT_API
158 int mm_session_get_current_type(int *sessiontype)
159 {
160         int result = MM_ERROR_NONE;
161         int ltype = 0;
162
163         debug_fenter();
164
165         if (sessiontype == NULL) {
166                 debug_error("input argument is NULL\n");
167                 return MM_ERROR_INVALID_ARGUMENT;
168         }
169
170         result = _mm_session_util_read_type(-1, &ltype);
171         if (result == MM_ERROR_NONE) {
172                 debug_log("Current process session type = [%d]\n", ltype);
173                 *sessiontype = ltype;
174         } else {
175                 debug_error("failed to get current process session type!!\n");
176         }
177
178         debug_fleave();
179
180         return result;
181 }
182
183 EXPORT_API
184 int mm_session_get_current_information(int *session_type, int *session_options)
185 {
186         int result = MM_ERROR_NONE;
187         int ltype = 0;
188         int loption = 0;
189
190         debug_fenter();
191
192         if (session_type == NULL) {
193                 debug_error("input argument is NULL\n");
194                 return MM_ERROR_INVALID_ARGUMENT;
195         }
196
197         result = _mm_session_util_read_information(-1, &ltype, &loption);
198         if (result == MM_ERROR_NONE) {
199                 debug_log("Current process session type = [%d], options = [%x]\n", ltype, loption);
200                 *session_type = ltype;
201                 *session_options = loption;
202         } else {
203                 debug_error("failed to get current process session type, option!!\n");
204         }
205
206         debug_fleave();
207
208         return result;
209 }
210
211 EXPORT_API
212 int mm_session_finish(void)
213 {
214         int result = MM_ERROR_NONE;
215         int sessiontype = MM_SESSION_TYPE_MEDIA;
216
217         debug_fenter();
218
219         result = _mm_session_util_read_type(-1, &sessiontype);
220         if (MM_ERROR_NONE != result) {
221                 debug_error("Can not read current type");
222                 return result;
223         }
224
225         /* Check monitor handle */
226         result = _mm_session_util_delete_information(-1);
227         if(result != MM_ERROR_NONE)
228                 return result;
229
230         debug_fleave();
231
232         return MM_ERROR_NONE;
233 }
234
235 EXPORT_API
236 int mm_session_remove_watch_callback(int watchevent, int watchstate)
237 {
238         debug_fenter();
239
240         debug_fleave();
241
242         return MM_ERROR_NOT_SUPPORT_API;
243 }
244
245 EXPORT_API
246 int mm_session_set_subsession(mm_subsession_t subsession, mm_subsession_option_t option)
247 {
248         debug_fenter();
249
250         debug_fleave();
251
252         return MM_ERROR_NOT_SUPPORT_API;
253 }
254
255 EXPORT_API
256 int mm_session_get_subsession(mm_subsession_t *subsession)
257 {
258         debug_fenter();
259
260         debug_fleave();
261
262         return MM_ERROR_NOT_SUPPORT_API;
263 }
264
265 EXPORT_API
266 int mm_session_set_subevent(mm_session_sub_t subevent)
267 {
268         debug_fenter();
269
270         debug_fleave();
271
272         return MM_ERROR_NOT_SUPPORT_API;
273 }
274
275 EXPORT_API
276 int mm_session_get_subevent(mm_session_sub_t *subevent)
277 {
278         debug_fenter();
279
280         debug_fleave();
281
282         return MM_ERROR_NOT_SUPPORT_API;
283 }
284
285 EXPORT_API
286 int mm_session_reset_resumption_info(void)
287 {
288         debug_fenter();
289
290         debug_fleave();
291
292         return MM_ERROR_NOT_SUPPORT_API;
293 }
294
295 EXPORT_API
296 int _mm_session_util_delete_information(int app_pid)
297 {
298         pid_t mypid;
299         char filename[MAX_FILE_LENGTH];
300
301         if(app_pid == -1)
302                 mypid = getpid();
303         else
304                 mypid = (pid_t)app_pid;
305
306         ////// DELETE SESSION TYPE /////////
307         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
308         if(-1 ==  unlink(filename))
309                 return MM_ERROR_FILE_NOT_FOUND;
310         ////// DELETE SESSION TYPE /////////
311
312         return MM_ERROR_NONE;
313 }
314
315 EXPORT_API
316 int _mm_session_util_write_type(int app_pid, int sessiontype)
317 {
318         pid_t mypid;
319         int fd = -1;
320         char filename[MAX_FILE_LENGTH];
321
322         if(sessiontype < MM_SESSION_TYPE_MEDIA || sessiontype >= MM_SESSION_TYPE_NUM) {
323                 return MM_ERROR_INVALID_ARGUMENT;
324         }
325
326         if(app_pid == -1)
327                 mypid = getpid();
328         else
329                 mypid = (pid_t)app_pid;
330
331         ////// WRITE SESSION TYPE /////////
332         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
333         fd = open(filename, O_WRONLY | O_CREAT, 0644 );
334         if(fd < 0) {
335                 debug_error("open() failed with %d",errno);
336                 return MM_ERROR_FILE_WRITE;
337         }
338         sessiontype = sessiontype << 16;
339         write(fd, &sessiontype, sizeof(int));
340         if(0 > fchmod (fd, 00777)) {
341                 debug_error("fchmod failed with %d", errno);
342         } else {
343                 debug_warning("write sessiontype(%d) to /tmp/mm_session_%d", sessiontype >> 16, mypid);
344         }
345         close(fd);
346         ////// WRITE SESSION TYPE /////////
347
348         return MM_ERROR_NONE;
349 }
350
351 EXPORT_API
352 int _mm_session_util_read_type(int app_pid, int *sessiontype)
353 {
354         pid_t mypid;
355         int fd = -1;
356         char filename[MAX_FILE_LENGTH];
357
358         debug_fenter();
359
360         if(sessiontype == NULL)
361                 return MM_ERROR_INVALID_ARGUMENT;
362
363         if(app_pid == -1)
364                 mypid = getpid();
365         else
366                 mypid = (pid_t)app_pid;
367
368         ////// READ SESSION TYPE /////////
369         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
370         fd = open(filename, O_RDONLY);
371         if(fd < 0) {
372                 return MM_ERROR_INVALID_HANDLE;
373         }
374         read(fd, sessiontype, sizeof(int));
375         *sessiontype = *sessiontype >> 16;
376         debug_warning("read sessiontype(%d) from /tmp/mm_session_%d", *sessiontype, mypid);
377         close(fd);
378         ////// READ SESSION TYPE /////////
379
380         debug_fleave();
381
382         return MM_ERROR_NONE;
383 }
384
385 EXPORT_API
386 int _mm_session_util_write_information(int app_pid, int session_type, int flags)
387 {
388         pid_t mypid;
389         int fd = -1;
390         char filename[MAX_FILE_LENGTH];
391         int result_info = 0;
392
393         if ((session_type != MM_SESSION_TYPE_REPLACED_BY_STREAM) &&
394             (session_type < MM_SESSION_TYPE_MEDIA || session_type >= MM_SESSION_TYPE_NUM)) {
395                 return MM_ERROR_INVALID_ARGUMENT;
396         }
397         if(flags < 0) {
398                 return MM_ERROR_INVALID_ARGUMENT;
399         }
400
401         if(app_pid == -1) {
402                 mypid = getpid();
403         } else {
404                 mypid = (pid_t)app_pid;
405         }
406
407         ////// WRITE SESSION INFO /////////
408         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
409         fd = open(filename, O_WRONLY | O_CREAT, 0644 );
410         if(fd < 0) {
411                 debug_error("open() failed with %d",errno);
412                 return MM_ERROR_FILE_WRITE;
413         }
414
415         result_info = (flags) | (session_type << 16);
416         write(fd, &result_info, sizeof(int));
417         if (0 > fchmod (fd, 00777)) {
418                 debug_error("fchmod failed with %d", errno);
419         } else {
420                 debug_warning("write session information(%x) to /tmp/mm_session_%d", result_info, mypid);
421         }
422         close(fd);
423         ////// WRITE SESSION INFO /////////
424
425         return MM_ERROR_NONE;
426 }
427
428 EXPORT_API
429 int _mm_session_util_read_information(int app_pid, int *session_type, int *flags)
430 {
431         pid_t mypid;
432         int fd = -1;
433         char filename[MAX_FILE_LENGTH];
434         int result_info = 0;
435
436         debug_fenter();
437
438         if(session_type == NULL || flags == NULL) {
439                 return MM_ERROR_INVALID_ARGUMENT;
440         }
441
442         if(app_pid == -1) {
443                 mypid = getpid();
444         } else {
445                 mypid = (pid_t)app_pid;
446         }
447
448         ////// READ SESSION INFO /////////
449         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d", mypid);
450         fd = open(filename, O_RDONLY);
451         if(fd < 0) {
452                 return MM_ERROR_INVALID_HANDLE;
453         }
454         read(fd, &result_info, sizeof(int));
455         *session_type = result_info >> 16;
456         *flags = result_info & 0x0000ffff;
457
458         debug_warning("read session_type(%d), session_option(%x) from /tmp/mm_session_%d", *session_type, *flags, mypid);
459         close(fd);
460         ////// READ SESSION INFO /////////
461
462         debug_fleave();
463
464         return MM_ERROR_NONE;
465 }
466
467 void __session_signal_handler(int signo)
468 {
469         char* filename = NULL;
470         char str_error[256];
471
472         debug_warning("ENTER, sig.num(%d)", signo);
473
474         /* signal block -------------- */
475         sigset_t old_mask, all_mask;
476         sigfillset(&all_mask);
477         sigprocmask(SIG_BLOCK, &all_mask, &old_mask);
478
479         filename = g_strdup_printf("/tmp/mm_session_%d", getpid());
480         if (!remove(filename)) {
481                 debug_log(" remove %s success\n", filename);
482         } else {
483                 strerror_r (errno, str_error, sizeof (str_error));
484                 debug_error(" remove %s failed with %s\n", filename, str_error);
485         }
486
487         g_free(filename);
488
489         sigprocmask(SIG_SETMASK, &old_mask, NULL);
490         /* signal unblock ------------ */
491
492         switch (signo) {
493         case SIGINT:
494                 sigaction(SIGINT, &session_int_old_action, NULL);
495                 raise(signo);
496                 break;
497         case SIGABRT:
498                 sigaction(SIGABRT, &session_abrt_old_action, NULL);
499                 raise(signo);
500                 break;
501         case SIGSEGV:
502                 sigaction(SIGSEGV, &session_segv_old_action, NULL);
503                 raise(signo);
504                 break;
505         case SIGTERM:
506                 sigaction(SIGTERM, &session_term_old_action, NULL);
507                 raise(signo);
508                 break;
509         case SIGSYS:
510                 sigaction(SIGSYS, &session_sys_old_action, NULL);
511                 raise(signo);
512                 break;
513         case SIGXCPU:
514                 sigaction(SIGXCPU, &session_xcpu_old_action, NULL);
515                 raise(signo);
516                 break;
517         default:
518                 break;
519         }
520
521         debug_warning("LEAVE");
522 }
523
524 __attribute__ ((constructor))
525 void __mmsession_initialize(void)
526 {
527         struct sigaction session_action;
528         session_action.sa_handler = __session_signal_handler;
529         session_action.sa_flags = SA_NOCLDSTOP;
530
531         debug_fenter();
532
533         sigemptyset(&session_action.sa_mask);
534
535         sigaction(SIGINT, &session_action, &session_int_old_action);
536         sigaction(SIGABRT, &session_action, &session_abrt_old_action);
537         sigaction(SIGSEGV, &session_action, &session_segv_old_action);
538         sigaction(SIGTERM, &session_action, &session_term_old_action);
539         sigaction(SIGSYS, &session_action, &session_sys_old_action);
540         sigaction(SIGXCPU, &session_action, &session_xcpu_old_action);
541
542         debug_fleave();
543 }
544
545 __attribute__ ((destructor))
546 void __mmsession_finalize(void)
547 {
548
549         debug_fenter();
550
551         _mm_session_util_delete_information(-1);
552
553         sigaction(SIGINT, &session_int_old_action, NULL);
554         sigaction(SIGABRT, &session_abrt_old_action, NULL);
555         sigaction(SIGSEGV, &session_segv_old_action, NULL);
556         sigaction(SIGTERM, &session_term_old_action, NULL);
557         sigaction(SIGSYS, &session_sys_old_action, NULL);
558         sigaction(SIGXCPU, &session_xcpu_old_action, NULL);
559
560         debug_fleave();
561 }
562