Fix float->int(short) clipping issue when playing ogg content
[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 <string.h>
25
26 #include <mm_error.h>
27 #include <mm_debug.h>
28
29 #include <gio/gio.h>
30
31 #include <sys/socket.h>
32 #include <sys/un.h>
33
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"
37
38 static pthread_t g_focus_work_thread_id = 0;
39
40
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);
44
45 enum {
46         FOCUS_FUNCTION_ACQUIRE,
47         FOCUS_FUNCTION_RELEASE,
48         FOCUS_FUNCTION_MAX,
49 };
50
51 typedef struct mm_sound_focus_function_intf {
52         const char *name;
53         focus_function_handler handler;
54 } mm_sound_focus_function_intf_t;
55
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
60         },
61         [FOCUS_FUNCTION_RELEASE] = {
62                 .name = FOCUS_FUNC_NAME_RELEASE,
63                 .handler = handle_release_focus
64         },
65 };
66
67 static const char* convert_error_string_from_int(int error)
68 {
69         switch (error) {
70         case MM_ERROR_NONE:
71                 return FOCUS_ERROR_NONE;
72
73         case MM_ERROR_INVALID_ARGUMENT:
74                 return FOCUS_ERROR_INVALID_PARAMETER;
75
76         case MM_ERROR_POLICY_BLOCKED:
77         case MM_ERROR_POLICY_INTERNAL:
78                 return FOCUS_ERROR_POLICY;
79
80         case MM_ERROR_SOUND_INVALID_STATE:
81                 return FOCUS_ERROR_INVALID_STATE;
82
83         case MM_ERROR_SOUND_INTERNAL:
84                 return FOCUS_ERROR_INTERNAL;
85
86         default:
87                 return FOCUS_ERROR_INTERNAL;
88         }
89 }
90
91 static int handle_acquire_focus(_mm_sound_mgr_focus_socket_param_t *param)
92 {
93         int ret = MM_ERROR_NONE;
94
95         debug_fenter();
96
97         ret = __mm_sound_mgr_focus_ipc_acquire_focus(param->pid, param->handle_id, param->focus_type,
98                                                                                                 param->option, param->ext_info, true);
99
100         debug_fleave();
101
102         return ret;
103 }
104
105 static int handle_release_focus(_mm_sound_mgr_focus_socket_param_t *param)
106 {
107         int ret = MM_ERROR_NONE;
108
109         debug_fenter();
110
111         ret = __mm_sound_mgr_focus_ipc_release_focus(param->pid, param->handle_id, param->focus_type,
112                                                                                                 param->option, param->ext_info, true);
113
114         debug_fleave();
115
116         return ret;
117 }
118
119 static int focus_functions_handler(_mm_sound_mgr_focus_socket_param_t *param)
120 {
121         int i = 0;
122         int ret = MM_ERROR_SOUND_INTERNAL;
123
124         if (param == NULL)
125                 return MM_ERROR_SOUND_INTERNAL;
126
127         debug_log("param[%p], function_name[%s]", param, param->func_name);
128
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);
132         }
133
134         return ret;
135 }
136
137 static void *thread_func(void *data)
138 {
139         int fd = -1;
140         int accepted_fd = -1;
141         char str_error[MAX_ERROR_LEN] = {'\0',};
142         _mm_sound_mgr_focus_socket_param_t read_data;
143         int rval = 0;
144         char ret_buf[MAX_ERROR_LEN] = {'\0',};
145
146         if (data == NULL) {
147                 debug_error("invalid data");
148                 pthread_exit(NULL);
149         }
150
151         fd = (int)data;
152
153         if (listen(fd, 5)) {
154                 strerror_r(errno, str_error, sizeof(str_error));
155                 debug_error("failed to listen(), err: %s", str_error);
156                 goto LEAVE;
157         }
158         debug_log("listen for fd [%d] success", fd);
159
160         do {
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);
165                         goto LEAVE;
166                 }
167
168                 debug_log("accepted fd [%d]", accepted_fd);
169
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);
179
180                         if ((ret = focus_functions_handler(&read_data)))
181                                 debug_log("failed to focus_function_handler(), err[0x%x]", ret);
182
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);
187                         }
188                 } else {
189                         debug_error("failed to read(), read size mismatched, rval(%d), expect size(%d)",
190                                                 rval, sizeof(_mm_sound_mgr_focus_socket_param_t));
191                 }
192
193                 close(accepted_fd);
194         } while (1);
195
196 LEAVE:
197         close(fd);
198         pthread_exit(NULL);
199 }
200
201 int MMSoundMgrFocusSocketInit(int *fd)
202 {
203         int socket_fd;
204         struct sockaddr_un addr_un;
205         char str_error[128] = {'\0',};
206
207         if (fd == NULL) {
208                 debug_error("input param fd is null");
209                 return MM_ERROR_INVALID_ARGUMENT;
210         }
211
212         socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
213         if (socket_fd < 0) {
214                 strerror_r(errno, str_error, sizeof(str_error));
215                 debug_error("failed to socket(), err: %s", str_error);
216                 goto LEAVE;
217         }
218
219         debug_log("focus server socket fd [%d]", socket_fd);
220
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));
224
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);
234                                 goto LEAVE;
235                         }
236                 } else {
237                         goto LEAVE;
238                 }
239         }
240
241         debug_log("focus server socket binding success");
242
243         *fd = socket_fd;
244
245         debug_leave();
246
247         return MM_ERROR_NONE;
248
249 LEAVE:
250         if (socket_fd >= 0)
251                 close(socket_fd);
252
253         return MM_ERROR_SOUND_INTERNAL;
254 }
255
256 void MMSoundMgrFocusSocketFini(int fd)
257 {
258         debug_enter();
259
260         if (g_focus_work_thread_id) {
261                 unlink(FOCUS_SERVER_SOCK);
262                 shutdown(fd, SHUT_RDWR);
263                 close(fd);
264                 pthread_join(g_focus_work_thread_id, NULL);
265                 debug_msg("pthread join well");
266                 g_focus_work_thread_id = 0;
267         }
268
269         debug_leave();
270 }
271
272 int MMSoundMgrFocusSocketReadyToWork(int fd)
273 {
274         debug_enter();
275
276         if (fd < 0) {
277                 debug_error("input param fd [%d] is not valid", fd);
278                 return MM_ERROR_INVALID_ARGUMENT;
279         }
280
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;
285         }
286
287         debug_leave();
288
289         return MM_ERROR_NONE;
290 }