162c552f823fab4834571cd16bcfe3e6d5aa3978
[platform/core/multimedia/libmm-sound.git] / focus_server / mm_sound_mgr_focus_socket.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Sangchul Lee <sc11.lee@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 <stdlib.h>
24 #include <stdint.h>
25 #include <string.h>
26
27 #include <mm_error.h>
28 #include <mm_debug.h>
29
30 #include <gio/gio.h>
31
32 #include <sys/socket.h>
33 #include <sys/un.h>
34
35 #include "../include/mm_sound_focus_socket.h"
36 #include "include/mm_sound_mgr_focus.h"
37 #include "include/mm_sound_mgr_focus_ipc.h"
38
39 static pthread_t g_focus_ready_thread_id = 0;
40
41 typedef int (*focus_function_handler) (int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
42 static int handle_register_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
43 static int handle_unregister_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
44 static int handle_add_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
45 static int handle_remove_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
46 static int handle_acquire_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
47 static int handle_release_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
48 static int handle_set_focus_reacquisition(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
49 static int handle_deliver_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
50 static int handle_get_acquired_focus_info(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
51
52 enum {
53         FOCUS_FUNCTION_REGISTER,
54         FOCUS_FUNCTION_UNREGISTER,
55         FOCUS_FUNCTION_ADD_WATCH,
56         FOCUS_FUNCTION_REMOVE_WATCH,
57         FOCUS_FUNCTION_ACQUIRE,
58         FOCUS_FUNCTION_RELEASE,
59         FOCUS_FUNCTION_SET_REACQUISITION,
60         FOCUS_FUNCTION_DELIVER,
61         FOCUS_FUNCTION_GET_ACQUIRED_INFO,
62         FOCUS_FUNCTION_MAX,
63 };
64
65 #define DEFAULT_FOCUS_THREAD_READY_TIMEOUT 5
66
67 typedef struct mm_sound_focus_thread_data {
68         const int *sockfd;
69         GMutex wait_mutex;
70         GCond wait_cond;
71         gboolean listen_ready;
72 } focus_thread_data_t;
73
74 typedef struct mm_sound_focus_function_intf {
75         const char *name;
76         focus_function_handler handler;
77 } mm_sound_focus_function_intf_t;
78
79 static mm_sound_focus_function_intf_t functions[FOCUS_FUNCTION_MAX] = {
80         [FOCUS_FUNCTION_REGISTER] = {
81                 .name = FOCUS_FUNC_NAME_REGISTER,
82                 .handler = handle_register_focus
83         },
84         [FOCUS_FUNCTION_UNREGISTER] = {
85                 .name = FOCUS_FUNC_NAME_UNREGISTER,
86                 .handler = handle_unregister_focus
87         },
88         [FOCUS_FUNCTION_ADD_WATCH] = {
89                 .name = FOCUS_FUNC_NAME_ADD_WATCH,
90                 .handler = handle_add_watch_focus
91         },
92         [FOCUS_FUNCTION_REMOVE_WATCH] = {
93                 .name = FOCUS_FUNC_NAME_REMOVE_WATCH,
94                 .handler = handle_remove_watch_focus
95         },
96         [FOCUS_FUNCTION_ACQUIRE] = {
97                 .name = FOCUS_FUNC_NAME_ACQUIRE,
98                 .handler = handle_acquire_focus
99         },
100         [FOCUS_FUNCTION_RELEASE] = {
101                 .name = FOCUS_FUNC_NAME_RELEASE,
102                 .handler = handle_release_focus
103         },
104         [FOCUS_FUNCTION_SET_REACQUISITION] = {
105                 .name = FOCUS_FUNC_NAME_SET_REACQUISITION,
106                 .handler = handle_set_focus_reacquisition
107         },
108         [FOCUS_FUNCTION_DELIVER] = {
109                 .name = FOCUS_FUNC_NAME_DELIVER,
110                 .handler = handle_deliver_focus
111         },
112         [FOCUS_FUNCTION_GET_ACQUIRED_INFO] = {
113                 .name = FOCUS_FUNC_NAME_GET_ACQUIRED_INFO,
114                 .handler = handle_get_acquired_focus_info
115         }
116 };
117
118 static int handle_register_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
119 {
120         int ret = MM_ERROR_NONE;
121
122         debug_fenter();
123
124         ret = __mm_sound_mgr_focus_ipc_register_focus(param->pid, fd, param->stream_type);
125         result->handle_id = fd;
126
127         debug_fleave();
128
129         return ret;
130 }
131
132 static int handle_unregister_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
133 {
134         int ret = MM_ERROR_NONE;
135
136         debug_fenter();
137
138         if (fd != param->handle_id) {
139                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
140                 return MM_ERROR_SOUND_INTERNAL;
141         }
142         ret = __mm_sound_mgr_focus_ipc_unregister_focus(param->pid, param->handle_id);
143
144         debug_fleave();
145
146         return ret;
147 }
148
149 static int handle_add_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
150 {
151         int ret = MM_ERROR_NONE;
152
153         debug_fenter();
154
155         ret = __mm_sound_mgr_focus_ipc_add_watch_node(param->pid, fd, param->focus_type);
156         result->handle_id = fd;
157
158         debug_fleave();
159
160         return ret;
161 }
162
163 static int handle_remove_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
164 {
165         int ret = MM_ERROR_NONE;
166
167         debug_fenter();
168
169         if (fd != param->handle_id) {
170                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
171                 return MM_ERROR_SOUND_INTERNAL;
172         }
173         ret = __mm_sound_mgr_focus_ipc_remove_watch_node(param->pid, param->handle_id);
174
175         debug_fleave();
176
177         return ret;
178 }
179
180 static int handle_acquire_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
181 {
182         int ret = MM_ERROR_NONE;
183
184         debug_fenter();
185
186         if (fd != param->handle_id) {
187                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
188                 return MM_ERROR_SOUND_INTERNAL;
189         }
190         ret = __mm_sound_mgr_focus_ipc_acquire_focus(param->pid, param->handle_id, param->focus_type,
191                                                                                                 param->option, param->ext_info, true);
192
193         debug_fleave();
194
195         return ret;
196 }
197
198 static int handle_release_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
199 {
200         int ret = MM_ERROR_NONE;
201
202         debug_fenter();
203
204         if (fd != param->handle_id) {
205                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
206                 return MM_ERROR_SOUND_INTERNAL;
207         }
208         ret = __mm_sound_mgr_focus_ipc_release_focus(param->pid, param->handle_id, param->focus_type,
209                                                                                                 param->option, param->ext_info, true);
210
211         debug_fleave();
212
213         return ret;
214 }
215
216 static int handle_set_focus_reacquisition(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
217 {
218         int ret = MM_ERROR_NONE;
219
220         debug_fenter();
221
222         if (fd != param->handle_id) {
223                 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
224                 return MM_ERROR_SOUND_INTERNAL;
225         }
226         ret = __mm_sound_mgr_focus_ipc_set_focus_reacquisition(param->pid, param->handle_id, param->reacquisition);
227
228         debug_fleave();
229
230         return ret;
231 }
232
233 static int handle_deliver_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
234 {
235         int ret = MM_ERROR_NONE;
236
237         debug_fenter();
238
239         ret = __mm_sound_mgr_focus_ipc_deliver_focus(param->pid, param->handle_id, param->handle_id_dst, param->focus_type);
240
241         debug_fleave();
242
243         return ret;
244 }
245
246 static int handle_get_acquired_focus_info(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
247 {
248         int ret = MM_ERROR_NONE;
249         char *res_stream_type = NULL;
250         char *res_ext_info = NULL;
251
252         debug_fenter();
253
254         if (!result) {
255                 debug_error("invalid arguments, result[%p]", result);
256                 return MM_ERROR_INVALID_ARGUMENT;
257         }
258
259         ret = __mm_sound_mgr_focus_ipc_get_acquired_focus_stream_type(param->focus_type, &res_stream_type, &result->option, &res_ext_info);
260         if (ret == MM_ERROR_NONE) {
261                 MMSOUND_STRNCPY(result->stream_type, res_stream_type, MM_SOUND_NAME_NUM);
262                 MMSOUND_STRNCPY(result->ext_info, res_ext_info, MM_SOUND_NAME_NUM);
263         }
264
265         debug_fleave();
266
267         return ret;
268 }
269
270 static int focus_functions_handler(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
271 {
272         int i = 0;
273         int ret = MM_ERROR_NONE;
274
275         if (param == NULL)
276                 return MM_ERROR_INVALID_ARGUMENT;
277
278         debug_msg("fd[%d], param[%p], function_name[%s]", fd, param, param->func_name);
279
280         for (i = 0; i < FOCUS_FUNCTION_MAX; i++) {
281                 if (!strncmp(param->func_name, functions[i].name, MAX_ERROR_LEN))
282                         ret = functions[i].handler(fd, param, result);
283         }
284
285         return ret;
286 }
287
288 static bool need_to_exit(const char *func_name)
289 {
290         if (!strncmp(func_name, FOCUS_FUNC_NAME_UNREGISTER, MM_SOUND_NAME_NUM) ||
291                 !strncmp(func_name, FOCUS_FUNC_NAME_REMOVE_WATCH, MM_SOUND_NAME_NUM) ||
292                 !strncmp(func_name, FOCUS_FUNC_NAME_GET_ACQUIRED_INFO, MM_SOUND_NAME_NUM))
293                 return true;
294
295         return false;
296 }
297
298
299 static focus_thread_data_t *__focus_thread_data_create(const int *sockfd)
300 {
301         focus_thread_data_t *thread_data = NULL;
302         thread_data = g_new0(focus_thread_data_t, 1);
303
304         thread_data->sockfd = sockfd;
305         g_mutex_init(&thread_data->wait_mutex);
306         g_cond_init(&thread_data->wait_cond);
307         thread_data->listen_ready = FALSE;
308
309         return thread_data;
310 }
311
312 static void __focus_thread_ready_signal(focus_thread_data_t *thread_data)
313 {
314         g_assert(thread_data);
315
316         g_mutex_lock(&thread_data->wait_mutex);
317
318         debug_msg("signaling focus thread ready!");
319         thread_data->listen_ready = TRUE;
320         g_cond_signal(&thread_data->wait_cond);
321
322         g_mutex_unlock(&thread_data->wait_mutex);
323 }
324
325 static gboolean __focus_thread_ready_wait(focus_thread_data_t *thread_data, int timeout_sec)
326 {
327         gint64 end_time;
328         g_autoptr(GMutexLocker) locker = NULL;
329
330         g_assert(thread_data);
331
332         locker = g_mutex_locker_new(&thread_data->wait_mutex);
333
334         end_time = g_get_monotonic_time() + timeout_sec * G_TIME_SPAN_SECOND;
335
336         while (!thread_data->listen_ready) {
337                 if (!g_cond_wait_until(&thread_data->wait_cond,
338                                                         &thread_data->wait_mutex,
339                                                         end_time)) {
340                         debug_error("timeout!!!");
341                         break;
342                 }
343                 debug_msg("wait done! ready:%d", thread_data->listen_ready);
344         }
345
346         return thread_data->listen_ready;
347 }
348
349 static void __focus_thread_data_destroy(focus_thread_data_t *thread_data)
350 {
351         g_assert(thread_data);
352
353         g_mutex_clear(&thread_data->wait_mutex);
354         g_cond_clear(&thread_data->wait_cond);
355
356         g_free(thread_data);
357 }
358
359 static void *work_thread_func(void *data)
360 {
361         int accepted_fd = -1;
362         char str_error[MAX_ERROR_LEN] = {'\0',};
363         _mm_sound_focus_socket_param_t read_data;
364         _mm_sound_focus_socket_result_t result;
365         int rval = 0;
366
367         debug_fenter();
368
369         if (!data) {
370                 debug_error("invalid data");
371                 pthread_exit(NULL);
372         }
373
374         accepted_fd = (int)(uintptr_t)(data);
375
376         while (1) {
377                 memset(&read_data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
378                 if ((rval = read(accepted_fd, &read_data, sizeof(_mm_sound_focus_socket_param_t))) < 0) {
379                         strerror_r(errno, str_error, sizeof(str_error));
380                         debug_error("failed to read(), err: %s", str_error);
381
382                 } else if (rval == sizeof(_mm_sound_focus_socket_param_t)) {
383                         int ret = MM_ERROR_NONE;
384
385                         debug_log("data read successfully, command[%s], pid[%d]",
386                                         read_data.func_name, read_data.pid);
387
388                         memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
389                         if ((ret = focus_functions_handler(accepted_fd, &read_data, &result)))
390                                 debug_error("failed to focus_function_handler(), err[0x%x]", ret);
391                         result.ret = ret;
392
393                         /* send result */
394                         if (write(accepted_fd, &result, sizeof(_mm_sound_focus_socket_result_t)) < 0) {
395                                 strerror_r(errno, str_error, sizeof(str_error));
396                                 debug_error("failed to write(), err: %s", str_error);
397                         }
398
399                         if (need_to_exit(read_data.func_name))
400                                 break;
401                 } else {
402                         debug_error("failed to read(), read size mismatched, rval(%d), expect size(%zu)",
403                                                 rval, sizeof(_mm_sound_focus_socket_param_t));
404                         break;
405                 }
406         }
407
408         /* clean-up FD and focus node */
409         mm_sound_mgr_focus_emergent_exit_by_id(accepted_fd);
410
411         debug_msg("now close fd[%d]", accepted_fd);
412         close(accepted_fd);
413
414         debug_fleave();
415
416         pthread_exit(NULL);
417 }
418
419 static void *ready_thread_func(void *data)
420 {
421         int accepted_fd = -1;
422         char str_error[MAX_ERROR_LEN] = {'\0',};
423         int ret = 0;
424         pthread_t focus_work_thread_id;
425         pthread_attr_t attr;
426
427         focus_thread_data_t *thread_data = (focus_thread_data_t *)data;
428
429         if (!thread_data) {
430                 debug_error("invalid data");
431                 pthread_exit(NULL);
432         }
433
434         debug_fenter();
435
436         ret = pthread_attr_init(&attr);
437         if (ret != 0) {
438                 debug_error("failed to init pthread attr, errno=%d", ret);
439                 goto LEAVE;
440         }
441
442         ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
443         if (ret != 0) {
444                 debug_error("failed to set detach state, errno=%d", ret);
445                 goto LEAVE;
446         }
447
448         if (listen(*thread_data->sockfd, 5)) {
449                 strerror_r(errno, str_error, sizeof(str_error));
450                 debug_error("failed to listen(), err: %s", str_error);
451                 goto LEAVE;
452         }
453         debug_msg("listen for fd [%d] success", *thread_data->sockfd);
454
455         __focus_thread_ready_signal(thread_data);
456
457         while (*thread_data->sockfd != -1) {
458                 accepted_fd = accept(*thread_data->sockfd, NULL, NULL);
459                 if (accepted_fd == -1) {
460                         strerror_r(errno, str_error, sizeof(str_error));
461                         debug_error("failed to accept(), err: %s", str_error);
462                         break;
463                 }
464
465                 debug_log("accepted fd [%d]", accepted_fd);
466
467                 if (pthread_create(&focus_work_thread_id, &attr, (void *)work_thread_func, (void *)(uintptr_t)accepted_fd)) {
468                         debug_error("failed to create work thread, accepted_fd(%d)", accepted_fd);
469                         break;
470                 }
471         }
472
473         __focus_thread_data_destroy(thread_data);
474
475 LEAVE:
476         pthread_attr_destroy(&attr);
477
478         debug_fleave();
479
480         pthread_exit(NULL);
481 }
482
483 int MMSoundMgrFocusSocketInit(int *sockfd)
484 {
485         int socket_fd;
486         struct sockaddr_un addr_un;
487         char str_error[128] = {'\0',};
488
489         if (!sockfd) {
490                 debug_error("input param fd is null");
491                 return MM_ERROR_INVALID_ARGUMENT;
492         }
493
494         socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
495         if (socket_fd < 0) {
496                 strerror_r(errno, str_error, sizeof(str_error));
497                 debug_error("failed to socket(), err: %s", str_error);
498                 goto LEAVE;
499         }
500
501         debug_msg("focus server socket fd [%d]", socket_fd);
502
503         memset(&addr_un, 0, sizeof(addr_un));
504         addr_un.sun_family = AF_UNIX;
505         strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path));
506
507         if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
508                 int errsv = errno;
509                 strerror_r(errsv, str_error, sizeof(str_error));
510                 debug_error("failed to bind(), err: %s", str_error);
511                 if (errsv == EADDRINUSE) {
512                         unlink(FOCUS_SERVER_SOCK);
513                         debug_msg("unlink socket and bind again...");
514                         if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
515                                 strerror_r(errno, str_error, sizeof(str_error));
516                                 debug_error("failed to bind() again, err: %s", str_error);
517                                 goto LEAVE;
518                         }
519                 } else {
520                         goto LEAVE;
521                 }
522         }
523
524         debug_msg("focus server socket binding success");
525
526         *sockfd = socket_fd;
527
528         debug_leave();
529
530         return MM_ERROR_NONE;
531
532 LEAVE:
533         if (socket_fd >= 0)
534                 close(socket_fd);
535
536         return MM_ERROR_SOUND_INTERNAL;
537 }
538
539 void MMSoundMgrFocusSocketFini(int *sockfd)
540 {
541         debug_enter();
542
543         if (g_focus_ready_thread_id) {
544                 unlink(FOCUS_SERVER_SOCK);
545
546                 if (*sockfd != -1) {
547                         shutdown(*sockfd, SHUT_RDWR);
548                         close(*sockfd);
549                         *sockfd = -1;
550                 }
551
552                 debug_msg("try pthread join for thread id:%lu", g_focus_ready_thread_id);
553                 pthread_join(g_focus_ready_thread_id, NULL);
554                 debug_msg("pthread joined well");
555                 g_focus_ready_thread_id = 0;
556         }
557
558         debug_leave();
559 }
560
561 int MMSoundMgrFocusSocketReadyToWork(const int *sockfd)
562 {
563         debug_enter();
564         focus_thread_data_t *thread_data = NULL;
565
566         if (*sockfd < 0) {
567                 debug_error("input param sockfd [%d] is not valid", *sockfd);
568                 return MM_ERROR_INVALID_ARGUMENT;
569         }
570
571         debug_msg("sockfd [%d]", *sockfd);
572
573         thread_data = __focus_thread_data_create(sockfd);
574
575         if (pthread_create(&g_focus_ready_thread_id, NULL, (void *)ready_thread_func, thread_data)) {
576                 debug_error("failed to create ready thread");
577                 goto ERROR_INTERNAL;
578         }
579
580         if (!__focus_thread_ready_wait(thread_data, DEFAULT_FOCUS_THREAD_READY_TIMEOUT)) {
581                 debug_error("focus thread is not ready for %u sec!!!", DEFAULT_FOCUS_THREAD_READY_TIMEOUT);
582                 goto ERROR_INTERNAL;
583         }
584
585         debug_leave();
586
587         return MM_ERROR_NONE;
588
589 ERROR_INTERNAL:
590         __focus_thread_data_destroy(thread_data);
591         return MM_ERROR_SOUND_INTERNAL;
592 }