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_work_thread_id = 0;
41 typedef int (*focus_function_handler) (_mm_sound_mgr_focus_socket_param_t *param);
42 static int handle_acquire_focus(_mm_sound_mgr_focus_socket_param_t *param);
43 static int handle_release_focus(_mm_sound_mgr_focus_socket_param_t *param);
46 FOCUS_FUNCTION_ACQUIRE,
47 FOCUS_FUNCTION_RELEASE,
51 typedef struct mm_sound_focus_function_intf {
53 focus_function_handler handler;
54 } mm_sound_focus_function_intf_t;
56 static mm_sound_focus_function_intf_t functions[FOCUS_FUNCTION_MAX] = {
57 [FOCUS_FUNCTION_ACQUIRE] = {
58 .name = FOCUS_FUNC_NAME_ACQUIRE,
59 .handler = handle_acquire_focus
61 [FOCUS_FUNCTION_RELEASE] = {
62 .name = FOCUS_FUNC_NAME_RELEASE,
63 .handler = handle_release_focus
67 static const char* convert_error_string_from_int(int error)
71 return FOCUS_ERROR_NONE;
73 case MM_ERROR_INVALID_ARGUMENT:
74 return FOCUS_ERROR_INVALID_PARAMETER;
76 case MM_ERROR_POLICY_BLOCKED:
77 case MM_ERROR_POLICY_INTERNAL:
78 return FOCUS_ERROR_POLICY;
80 case MM_ERROR_SOUND_INVALID_STATE:
81 return FOCUS_ERROR_INVALID_STATE;
83 case MM_ERROR_SOUND_INTERNAL:
84 return FOCUS_ERROR_INTERNAL;
87 return FOCUS_ERROR_INTERNAL;
91 static int handle_acquire_focus(_mm_sound_mgr_focus_socket_param_t *param)
93 int ret = MM_ERROR_NONE;
97 ret = __mm_sound_mgr_focus_ipc_acquire_focus(param->pid, param->handle_id, param->focus_type,
98 param->option, param->ext_info, true);
105 static int handle_release_focus(_mm_sound_mgr_focus_socket_param_t *param)
107 int ret = MM_ERROR_NONE;
111 ret = __mm_sound_mgr_focus_ipc_release_focus(param->pid, param->handle_id, param->focus_type,
112 param->option, param->ext_info, true);
119 static int focus_functions_handler(_mm_sound_mgr_focus_socket_param_t *param)
122 int ret = MM_ERROR_SOUND_INTERNAL;
125 return MM_ERROR_SOUND_INTERNAL;
127 debug_log("param[%p], function_name[%s]", param, param->func_name);
129 for (i = 0; i < FOCUS_FUNCTION_MAX; i++) {
130 if (!strncmp(param->func_name, functions[i].name, MAX_ERROR_LEN))
131 ret = functions[i].handler(param);
137 static void *thread_func(void *data)
140 int accepted_fd = -1;
141 char str_error[MAX_ERROR_LEN] = {'\0',};
142 _mm_sound_mgr_focus_socket_param_t read_data;
144 char ret_buf[MAX_ERROR_LEN] = {'\0',};
147 debug_error("invalid data");
154 strerror_r(errno, str_error, sizeof(str_error));
155 debug_error("failed to listen(), err: %s", str_error);
158 debug_log("listen for fd [%d] success", fd);
161 accepted_fd = accept(fd, NULL, NULL);
162 if (accepted_fd == -1) {
163 strerror_r(errno, str_error, sizeof(str_error));
164 debug_error("failed to accept(), err: %s", str_error);
168 debug_log("accepted fd [%d]", accepted_fd);
170 memset(&read_data, 0x00, sizeof(_mm_sound_mgr_focus_socket_param_t));
171 if ((rval = read(accepted_fd, &read_data, sizeof(_mm_sound_mgr_focus_socket_param_t))) < 0) {
172 strerror_r(errno, str_error, sizeof(str_error));
173 debug_error("failed to read(), err: %s", str_error);
174 } else if (rval == sizeof(_mm_sound_mgr_focus_socket_param_t)) {
175 int ret = MM_ERROR_NONE;
176 debug_log("data read successfully..");
177 debug_log(" : pid[%d], handle_id[%d], focus_type[%d]", read_data.pid, read_data.handle_id, read_data.focus_type);
178 debug_log(" : option[%d], ext_info[%s]", read_data.option, read_data.ext_info);
180 if ((ret = focus_functions_handler(&read_data)))
181 debug_log("failed to focus_function_handler(), err[0x%x]", ret);
183 snprintf(ret_buf, sizeof(ret_buf), "%s", convert_error_string_from_int(ret));
184 if (write(accepted_fd, ret_buf, sizeof(ret_buf)) < 0) {
185 strerror_r(errno, str_error, sizeof(str_error));
186 debug_error("failed to write(), err: %s", str_error);
189 debug_error("failed to read(), read size mismatched, rval(%d), expect size(%d)",
190 rval, sizeof(_mm_sound_mgr_focus_socket_param_t));
201 int MMSoundMgrFocusSocketInit(int *fd)
204 struct sockaddr_un addr_un;
205 char str_error[128] = {'\0',};
208 debug_error("input param fd is null");
209 return MM_ERROR_INVALID_ARGUMENT;
212 socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
214 strerror_r(errno, str_error, sizeof(str_error));
215 debug_error("failed to socket(), err: %s", str_error);
219 debug_log("focus server socket fd [%d]", socket_fd);
221 memset(&addr_un, 0, sizeof(addr_un));
222 addr_un.sun_family = AF_UNIX;
223 strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path));
225 if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
226 strerror_r(errno, str_error, sizeof(str_error));
227 debug_error("failed to bind(), err: %s", str_error);
228 if (errno == EADDRINUSE) {
229 unlink(FOCUS_SERVER_SOCK);
230 debug_msg("unlink socket and bind again...");
231 if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
232 strerror_r(errno, str_error, sizeof(str_error));
233 debug_error("failed to bind() again, err: %s", str_error);
241 debug_log("focus server socket binding success");
247 return MM_ERROR_NONE;
253 return MM_ERROR_SOUND_INTERNAL;
256 void MMSoundMgrFocusSocketFini(int fd)
260 if (g_focus_work_thread_id) {
261 unlink(FOCUS_SERVER_SOCK);
262 shutdown(fd, SHUT_RDWR);
264 pthread_join(g_focus_work_thread_id, NULL);
265 debug_msg("pthread join well");
266 g_focus_work_thread_id = 0;
272 int MMSoundMgrFocusSocketReadyToWork(int fd)
277 debug_error("input param fd [%d] is not valid", fd);
278 return MM_ERROR_INVALID_ARGUMENT;
281 debug_log("fd [%d]", fd);
282 if (pthread_create(&g_focus_work_thread_id, NULL, (void *)thread_func, (void *)fd)) {
283 debug_error("failed to start work thread");
284 return MM_ERROR_SOUND_INTERNAL;
289 return MM_ERROR_NONE;