4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Sangchul Lee <sc11.lee@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.
31 #include <sys/socket.h>
34 #include "../include/mm_sound_focus_socket.h"
35 #include "include/mm_sound_mgr_focus.h"
36 #include "include/mm_sound_mgr_focus_ipc.h"
38 static pthread_t g_focus_ready_thread_id = 0;
40 typedef int (*focus_function_handler) (int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
41 static int handle_register_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
42 static int handle_unregister_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
43 static int handle_add_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
44 static int handle_remove_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
45 static int handle_acquire_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
46 static int handle_release_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
47 static int handle_set_focus_reacquisition(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
48 static int handle_deliver_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
49 static int handle_get_acquired_focus_info(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result);
52 FOCUS_FUNCTION_REGISTER,
53 FOCUS_FUNCTION_UNREGISTER,
54 FOCUS_FUNCTION_ADD_WATCH,
55 FOCUS_FUNCTION_REMOVE_WATCH,
56 FOCUS_FUNCTION_ACQUIRE,
57 FOCUS_FUNCTION_RELEASE,
58 FOCUS_FUNCTION_SET_REACQUISITION,
59 FOCUS_FUNCTION_DELIVER,
60 FOCUS_FUNCTION_GET_ACQUIRED_INFO,
64 typedef struct mm_sound_focus_function_intf {
66 focus_function_handler handler;
67 } mm_sound_focus_function_intf_t;
69 static mm_sound_focus_function_intf_t functions[FOCUS_FUNCTION_MAX] = {
70 [FOCUS_FUNCTION_REGISTER] = {
71 .name = FOCUS_FUNC_NAME_REGISTER,
72 .handler = handle_register_focus
74 [FOCUS_FUNCTION_UNREGISTER] = {
75 .name = FOCUS_FUNC_NAME_UNREGISTER,
76 .handler = handle_unregister_focus
78 [FOCUS_FUNCTION_ADD_WATCH] = {
79 .name = FOCUS_FUNC_NAME_ADD_WATCH,
80 .handler = handle_add_watch_focus
82 [FOCUS_FUNCTION_REMOVE_WATCH] = {
83 .name = FOCUS_FUNC_NAME_REMOVE_WATCH,
84 .handler = handle_remove_watch_focus
86 [FOCUS_FUNCTION_ACQUIRE] = {
87 .name = FOCUS_FUNC_NAME_ACQUIRE,
88 .handler = handle_acquire_focus
90 [FOCUS_FUNCTION_RELEASE] = {
91 .name = FOCUS_FUNC_NAME_RELEASE,
92 .handler = handle_release_focus
94 [FOCUS_FUNCTION_SET_REACQUISITION] = {
95 .name = FOCUS_FUNC_NAME_SET_REACQUISITON,
96 .handler = handle_set_focus_reacquisition
98 [FOCUS_FUNCTION_DELIVER] = {
99 .name = FOCUS_FUNC_NAME_DELIVER,
100 .handler = handle_deliver_focus
102 [FOCUS_FUNCTION_GET_ACQUIRED_INFO] = {
103 .name = FOCUS_FUNC_NAME_GET_ACQUIRED_INFO,
104 .handler = handle_get_acquired_focus_info
108 static int handle_register_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
110 int ret = MM_ERROR_NONE;
114 ret = __mm_sound_mgr_focus_ipc_register_focus(param->pid, fd, param->stream_type);
115 result->handle_id = fd;
122 static int handle_unregister_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
124 int ret = MM_ERROR_NONE;
128 if (fd != param->handle_id) {
129 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
130 return MM_ERROR_SOUND_INTERNAL;
132 ret = __mm_sound_mgr_focus_ipc_unregister_focus(param->pid, param->handle_id);
139 static int handle_add_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
141 int ret = MM_ERROR_NONE;
145 ret = __mm_sound_mgr_focus_ipc_add_watch_node(param->pid, fd, param->focus_type);
146 result->handle_id = fd;
153 static int handle_remove_watch_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
155 int ret = MM_ERROR_NONE;
159 if (fd != param->handle_id) {
160 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
161 return MM_ERROR_SOUND_INTERNAL;
163 ret = __mm_sound_mgr_focus_ipc_remove_watch_node(param->pid, param->handle_id);
170 static int handle_acquire_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
172 int ret = MM_ERROR_NONE;
176 if (fd != param->handle_id) {
177 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
178 return MM_ERROR_SOUND_INTERNAL;
180 ret = __mm_sound_mgr_focus_ipc_acquire_focus(param->pid, param->handle_id, param->focus_type,
181 param->option, param->ext_info, true);
188 static int handle_release_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
190 int ret = MM_ERROR_NONE;
194 if (fd != param->handle_id) {
195 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
196 return MM_ERROR_SOUND_INTERNAL;
198 ret = __mm_sound_mgr_focus_ipc_release_focus(param->pid, param->handle_id, param->focus_type,
199 param->option, param->ext_info, true);
206 static int handle_set_focus_reacquisition(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
208 int ret = MM_ERROR_NONE;
212 if (fd != param->handle_id) {
213 debug_error("fd[%d] does not match with handle_id[%d] from param", fd, param->handle_id);
214 return MM_ERROR_SOUND_INTERNAL;
216 ret = __mm_sound_mgr_focus_ipc_set_focus_reacquisition(param->pid, param->handle_id, param->reacquisition);
223 static int handle_deliver_focus(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
225 int ret = MM_ERROR_NONE;
229 ret = __mm_sound_mgr_focus_ipc_deliver_focus(param->pid, param->handle_id, param->handle_id_dst, param->focus_type);
236 static int handle_get_acquired_focus_info(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
238 int ret = MM_ERROR_NONE;
239 char *res_stream_type = NULL;
240 char *res_ext_info = NULL;
245 debug_error("invalid arguments, result[%p]", result);
246 return MM_ERROR_INVALID_ARGUMENT;
249 ret = __mm_sound_mgr_focus_ipc_get_acquired_focus_stream_type(param->focus_type, &res_stream_type, &result->option, &res_ext_info);
250 if (ret == MM_ERROR_NONE) {
251 MMSOUND_STRNCPY(result->stream_type, res_stream_type, MM_SOUND_NAME_NUM);
252 MMSOUND_STRNCPY(result->ext_info, res_ext_info, MM_SOUND_NAME_NUM);
260 static int focus_functions_handler(int fd, _mm_sound_focus_socket_param_t *param, _mm_sound_focus_socket_result_t *result)
263 int ret = MM_ERROR_NONE;
266 return MM_ERROR_INVALID_ARGUMENT;
268 debug_log("fd[%d], param[%p], function_name[%s]", fd, param, param->func_name);
270 for (i = 0; i < FOCUS_FUNCTION_MAX; i++) {
271 if (!strncmp(param->func_name, functions[i].name, MAX_ERROR_LEN))
272 ret = functions[i].handler(fd, param, result);
278 static bool need_to_exit(const char *func_name)
280 if (!strncmp(func_name, FOCUS_FUNC_NAME_UNREGISTER, MM_SOUND_NAME_NUM) ||
281 !strncmp(func_name, FOCUS_FUNC_NAME_REMOVE_WATCH, MM_SOUND_NAME_NUM) ||
282 !strncmp(func_name, FOCUS_FUNC_NAME_GET_ACQUIRED_INFO, MM_SOUND_NAME_NUM))
288 static void* work_thread_func(void *data)
290 int accepted_fd = -1;
291 char str_error[MAX_ERROR_LEN] = {'\0',};
292 _mm_sound_focus_socket_param_t read_data;
293 _mm_sound_focus_socket_result_t result;
297 debug_error("invalid data");
303 accepted_fd = (int)(data);
306 memset(&read_data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
307 if ((rval = read(accepted_fd, &read_data, sizeof(_mm_sound_focus_socket_param_t))) < 0) {
308 strerror_r(errno, str_error, sizeof(str_error));
309 debug_error("failed to read(), err: %s", str_error);
311 } else if (rval == sizeof(_mm_sound_focus_socket_param_t)) {
312 int ret = MM_ERROR_NONE;
314 debug_log("data read successfully, command[%s], pid[%d]",
315 read_data.func_name, read_data.pid);
317 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
318 if ((ret = focus_functions_handler(accepted_fd, &read_data, &result)))
319 debug_error("failed to focus_function_handler(), err[0x%x]", ret);
323 if (write(accepted_fd, &result, sizeof(_mm_sound_focus_socket_result_t)) < 0) {
324 strerror_r(errno, str_error, sizeof(str_error));
325 debug_error("failed to write(), err: %s", str_error);
328 if (need_to_exit(read_data.func_name))
331 debug_error("failed to read(), read size mismatched, rval(%d), expect size(%d)",
332 rval, sizeof(_mm_sound_focus_socket_param_t));
339 debug_log("now close fd[%d]", accepted_fd);
340 /* clean-up FD and focus node */
341 mm_sound_mgr_focus_emergent_exit_by_id(accepted_fd);
346 static void* ready_thread_func(void *data)
349 int accepted_fd = -1;
350 char str_error[MAX_ERROR_LEN] = {'\0',};
352 pthread_t focus_work_thread_id;
356 debug_error("invalid data");
362 ret = pthread_attr_init(&attr);
364 debug_error("failed to init pthread attr, errno=%d", ret);
368 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
370 debug_error("failed to set detach state, errno=%d", ret);
377 strerror_r(errno, str_error, sizeof(str_error));
378 debug_error("failed to listen(), err: %s", str_error);
381 debug_log("listen for fd [%d] success", fd);
384 accepted_fd = accept(fd, NULL, NULL);
385 if (accepted_fd == -1) {
386 strerror_r(errno, str_error, sizeof(str_error));
387 debug_error("failed to accept(), err: %s", str_error);
391 debug_log("accepted fd [%d]", accepted_fd);
393 if (pthread_create(&focus_work_thread_id, &attr, (void *)work_thread_func, (void *)accepted_fd)) {
394 debug_error("failed to create work thread, accepted_fd(%d)", accepted_fd);
402 pthread_attr_destroy(&attr);
408 int MMSoundMgrFocusSocketInit(int *fd)
411 struct sockaddr_un addr_un;
412 char str_error[128] = {'\0',};
415 debug_error("input param fd is null");
416 return MM_ERROR_INVALID_ARGUMENT;
419 socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
421 strerror_r(errno, str_error, sizeof(str_error));
422 debug_error("failed to socket(), err: %s", str_error);
426 debug_log("focus server socket fd [%d]", socket_fd);
428 memset(&addr_un, 0, sizeof(addr_un));
429 addr_un.sun_family = AF_UNIX;
430 strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path));
432 if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
433 strerror_r(errno, str_error, sizeof(str_error));
434 debug_error("failed to bind(), err: %s", str_error);
435 if (errno == EADDRINUSE) {
436 unlink(FOCUS_SERVER_SOCK);
437 debug_msg("unlink socket and bind again...");
438 if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
439 strerror_r(errno, str_error, sizeof(str_error));
440 debug_error("failed to bind() again, err: %s", str_error);
448 debug_log("focus server socket binding success");
454 return MM_ERROR_NONE;
460 return MM_ERROR_SOUND_INTERNAL;
463 void MMSoundMgrFocusSocketFini(int fd)
467 if (g_focus_ready_thread_id) {
468 unlink(FOCUS_SERVER_SOCK);
469 shutdown(fd, SHUT_RDWR);
471 pthread_join(g_focus_ready_thread_id, NULL);
472 debug_msg("pthread join well");
473 g_focus_ready_thread_id = 0;
479 int MMSoundMgrFocusSocketReadyToWork(int fd)
484 debug_error("input param fd [%d] is not valid", fd);
485 return MM_ERROR_INVALID_ARGUMENT;
488 debug_log("fd [%d]", fd);
489 if (pthread_create(&g_focus_ready_thread_id, NULL, (void *)ready_thread_func, (void *)fd)) {
490 debug_error("failed to create ready thread");
491 return MM_ERROR_SOUND_INTERNAL;
496 return MM_ERROR_NONE;