OSDN Git Service

android/audio: Add audio_ipc_cleanup function
[android-x86/external-bluetooth-bluez.git] / android / hal-audio.c
1 /*
2  * Copyright (C) 2013 Intel Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <errno.h>
19 #include <pthread.h>
20 #include <poll.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <unistd.h>
27
28 #include <hardware/audio.h>
29 #include <hardware/hardware.h>
30
31 #include "audio-msg.h"
32 #include "hal-log.h"
33
34 static int listen_sk = -1;
35 static int audio_sk = -1;
36 static bool close_thread = false;
37
38 static pthread_t ipc_th = 0;
39 static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
40
41 struct a2dp_audio_dev {
42         struct audio_hw_device dev;
43         struct audio_stream_out *out;
44 };
45
46 static void audio_ipc_cleanup(void)
47 {
48         if (audio_sk >= 0) {
49                 shutdown(audio_sk, SHUT_RDWR);
50                 audio_sk = -1;
51         }
52 }
53
54 static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
55                                                                 size_t bytes)
56 {
57         DBG("");
58         return -ENOSYS;
59 }
60
61 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
62 {
63         DBG("");
64         return -ENOSYS;
65 }
66
67 static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
68 {
69         DBG("");
70         return -ENOSYS;
71 }
72
73 static size_t out_get_buffer_size(const struct audio_stream *stream)
74 {
75         DBG("");
76         return -ENOSYS;
77 }
78
79 static uint32_t out_get_channels(const struct audio_stream *stream)
80 {
81         DBG("");
82         return -ENOSYS;
83 }
84
85 static audio_format_t out_get_format(const struct audio_stream *stream)
86 {
87         DBG("");
88         return -ENOSYS;
89 }
90
91 static int out_set_format(struct audio_stream *stream, audio_format_t format)
92 {
93         DBG("");
94         return -ENOSYS;
95 }
96
97 static int out_standby(struct audio_stream *stream)
98 {
99         DBG("");
100         return -ENOSYS;
101 }
102
103 static int out_dump(const struct audio_stream *stream, int fd)
104 {
105         DBG("");
106         return -ENOSYS;
107 }
108
109 static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
110 {
111         DBG("");
112         return -ENOSYS;
113 }
114
115 static char *out_get_parameters(const struct audio_stream *stream,
116                                                         const char *keys)
117 {
118         DBG("");
119         return strdup("");
120 }
121
122 static uint32_t out_get_latency(const struct audio_stream_out *stream)
123 {
124         DBG("");
125         return -ENOSYS;
126 }
127
128 static int out_set_volume(struct audio_stream_out *stream, float left,
129                                                                 float right)
130 {
131         DBG("");
132         /* volume controlled in audioflinger mixer (digital) */
133         return -ENOSYS;
134 }
135
136 static int out_get_render_position(const struct audio_stream_out *stream,
137                                                         uint32_t *dsp_frames)
138 {
139         DBG("");
140         return -ENOSYS;
141 }
142
143 static int out_add_audio_effect(const struct audio_stream *stream,
144                                                         effect_handle_t effect)
145 {
146         DBG("");
147         return -ENOSYS;
148 }
149
150 static int out_remove_audio_effect(const struct audio_stream *stream,
151                                                         effect_handle_t effect)
152 {
153         DBG("");
154         return -ENOSYS;
155 }
156
157 static uint32_t in_get_sample_rate(const struct audio_stream *stream)
158 {
159         DBG("");
160         return -ENOSYS;
161 }
162
163 static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
164 {
165         DBG("");
166         return -ENOSYS;
167 }
168
169 static size_t in_get_buffer_size(const struct audio_stream *stream)
170 {
171         DBG("");
172         return -ENOSYS;
173 }
174
175 static uint32_t in_get_channels(const struct audio_stream *stream)
176 {
177         DBG("");
178         return -ENOSYS;
179 }
180
181 static audio_format_t in_get_format(const struct audio_stream *stream)
182 {
183         DBG("");
184         return -ENOSYS;
185 }
186
187 static int in_set_format(struct audio_stream *stream, audio_format_t format)
188 {
189         DBG("");
190         return -ENOSYS;
191 }
192
193 static int in_standby(struct audio_stream *stream)
194 {
195         DBG("");
196         return -ENOSYS;
197 }
198
199 static int in_dump(const struct audio_stream *stream, int fd)
200 {
201         DBG("");
202         return -ENOSYS;
203 }
204
205 static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
206 {
207         DBG("");
208         return -ENOSYS;
209 }
210
211 static char *in_get_parameters(const struct audio_stream *stream,
212                                                         const char *keys)
213 {
214         DBG("");
215         return strdup("");
216 }
217
218 static int in_set_gain(struct audio_stream_in *stream, float gain)
219 {
220         DBG("");
221         return -ENOSYS;
222 }
223
224 static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
225                                                                 size_t bytes)
226 {
227         DBG("");
228         return -ENOSYS;
229 }
230
231 static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
232 {
233         DBG("");
234         return -ENOSYS;
235 }
236
237 static int in_add_audio_effect(const struct audio_stream *stream,
238                                                         effect_handle_t effect)
239 {
240         DBG("");
241         return -ENOSYS;
242 }
243
244 static int in_remove_audio_effect(const struct audio_stream *stream,
245                                                         effect_handle_t effect)
246 {
247         DBG("");
248         return -ENOSYS;
249 }
250
251 static int audio_open_output_stream(struct audio_hw_device *dev,
252                                         audio_io_handle_t handle,
253                                         audio_devices_t devices,
254                                         audio_output_flags_t flags,
255                                         struct audio_config *config,
256                                         struct audio_stream_out **stream_out)
257
258 {
259         struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *) dev;
260         struct audio_stream_out *out;
261
262         out = calloc(1, sizeof(struct audio_stream_out));
263         if (!out)
264                 return -ENOMEM;
265
266         DBG("");
267
268         out->common.get_sample_rate = out_get_sample_rate;
269         out->common.set_sample_rate = out_set_sample_rate;
270         out->common.get_buffer_size = out_get_buffer_size;
271         out->common.get_channels = out_get_channels;
272         out->common.get_format = out_get_format;
273         out->common.set_format = out_set_format;
274         out->common.standby = out_standby;
275         out->common.dump = out_dump;
276         out->common.set_parameters = out_set_parameters;
277         out->common.get_parameters = out_get_parameters;
278         out->common.add_audio_effect = out_add_audio_effect;
279         out->common.remove_audio_effect = out_remove_audio_effect;
280         out->get_latency = out_get_latency;
281         out->set_volume = out_set_volume;
282         out->write = out_write;
283         out->get_render_position = out_get_render_position;
284
285         *stream_out = out;
286         a2dp_dev->out = out;
287
288         return 0;
289 }
290
291 static void audio_close_output_stream(struct audio_hw_device *dev,
292                                         struct audio_stream_out *stream)
293 {
294         struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *) dev;
295
296         DBG("");
297
298         free(stream);
299         a2dp_dev->out = NULL;
300 }
301
302 static int audio_set_parameters(struct audio_hw_device *dev,
303                                                         const char *kvpairs)
304 {
305         DBG("");
306         return -ENOSYS;
307 }
308
309 static char *audio_get_parameters(const struct audio_hw_device *dev,
310                                                         const char *keys)
311 {
312         DBG("");
313         return strdup("");
314 }
315
316 static int audio_init_check(const struct audio_hw_device *dev)
317 {
318         DBG("");
319         return -ENOSYS;
320 }
321
322 static int audio_set_voice_volume(struct audio_hw_device *dev, float volume)
323 {
324         DBG("");
325         return -ENOSYS;
326 }
327
328 static int audio_set_master_volume(struct audio_hw_device *dev, float volume)
329 {
330         DBG("");
331         return -ENOSYS;
332 }
333
334 static int audio_set_mode(struct audio_hw_device *dev, int mode)
335 {
336         DBG("");
337         return -ENOSYS;
338 }
339
340 static int audio_set_mic_mute(struct audio_hw_device *dev, bool state)
341 {
342         DBG("");
343         return -ENOSYS;
344 }
345
346 static int audio_get_mic_mute(const struct audio_hw_device *dev, bool *state)
347 {
348         DBG("");
349         return -ENOSYS;
350 }
351
352 static size_t audio_get_input_buffer_size(const struct audio_hw_device *dev,
353                                         const struct audio_config *config)
354 {
355         DBG("");
356         return -ENOSYS;
357 }
358
359 static int audio_open_input_stream(struct audio_hw_device *dev,
360                                         audio_io_handle_t handle,
361                                         audio_devices_t devices,
362                                         struct audio_config *config,
363                                         struct audio_stream_in **stream_in)
364 {
365         struct audio_stream_in *in;
366
367         DBG("");
368
369         in = calloc(1, sizeof(struct audio_stream_in));
370         if (!in)
371                 return -ENOMEM;
372
373         in->common.get_sample_rate = in_get_sample_rate;
374         in->common.set_sample_rate = in_set_sample_rate;
375         in->common.get_buffer_size = in_get_buffer_size;
376         in->common.get_channels = in_get_channels;
377         in->common.get_format = in_get_format;
378         in->common.set_format = in_set_format;
379         in->common.standby = in_standby;
380         in->common.dump = in_dump;
381         in->common.set_parameters = in_set_parameters;
382         in->common.get_parameters = in_get_parameters;
383         in->common.add_audio_effect = in_add_audio_effect;
384         in->common.remove_audio_effect = in_remove_audio_effect;
385         in->set_gain = in_set_gain;
386         in->read = in_read;
387         in->get_input_frames_lost = in_get_input_frames_lost;
388
389         *stream_in = in;
390
391         return 0;
392 }
393
394 static void audio_close_input_stream(struct audio_hw_device *dev,
395                                         struct audio_stream_in *stream_in)
396 {
397         DBG("");
398         free(stream_in);
399 }
400
401 static int audio_dump(const audio_hw_device_t *device, int fd)
402 {
403         DBG("");
404         return -ENOSYS;
405 }
406
407 static int audio_close(hw_device_t *device)
408 {
409         struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *)device;
410
411         DBG("");
412
413         pthread_mutex_lock(&close_mutex);
414         audio_ipc_cleanup();
415         close_thread = true;
416         pthread_mutex_unlock(&close_mutex);
417
418         pthread_join(ipc_th, NULL);
419
420         close(listen_sk);
421         listen_sk = -1;
422
423         free(a2dp_dev);
424         return 0;
425 }
426
427 static void *ipc_handler(void *data)
428 {
429         bool done = false;
430         struct pollfd pfd;
431
432         DBG("");
433
434         while (!done) {
435                 DBG("Waiting for connection ...");
436                 audio_sk = accept(listen_sk, NULL, NULL);
437                 if (audio_sk < 0) {
438                         int err = errno;
439                         error("audio: Failed to accept socket: %d (%s)", err,
440                                                                 strerror(err));
441                         continue;
442                 }
443
444                 DBG("Audio IPC: Connected");
445
446                 memset(&pfd, 0, sizeof(pfd));
447                 pfd.fd = audio_sk;
448                 pfd.events = POLLHUP | POLLERR | POLLNVAL;
449
450                 /* Check if socket is still alive. Empty while loop.*/
451                 while (poll(&pfd, 1, -1) < 0 && errno == EINTR);
452
453                 if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) {
454                         info("Audio HAL: Socket closed");
455                         audio_sk = -1;
456                 }
457
458                 /*Check if audio_dev is closed */
459                 pthread_mutex_lock(&close_mutex);
460                 done = close_thread;
461                 close_thread = false;
462                 pthread_mutex_unlock(&close_mutex);
463         }
464
465         info("Closing Audio IPC thread");
466         return NULL;
467 }
468
469 static int audio_ipc_init(void)
470 {
471         struct sockaddr_un addr;
472         int err;
473         int sk;
474
475         DBG("");
476
477         sk = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
478         if (sk < 0) {
479                 err = errno;
480                 error("audio: Failed to create socket: %d (%s)", err,
481                                                                 strerror(err));
482                 return err;
483         }
484
485         memset(&addr, 0, sizeof(addr));
486         addr.sun_family = AF_UNIX;
487
488         memcpy(addr.sun_path, BLUEZ_AUDIO_SK_PATH,
489                                         sizeof(BLUEZ_AUDIO_SK_PATH));
490
491         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
492                 err = errno;
493                 error("audio: Failed to bind socket: %d (%s)", err,
494                                                                 strerror(err));
495                 goto failed;
496         }
497
498         if (listen(sk, 1) < 0) {
499                 err = errno;
500                 error("audio: Failed to listen on the socket: %d (%s)", err,
501                                                                 strerror(err));
502                 goto failed;
503         }
504
505         listen_sk = sk;
506
507         err = pthread_create(&ipc_th, NULL, ipc_handler, NULL);
508         if (err) {
509                 err = -err;
510                 ipc_th = 0;
511                 error("audio: Failed to start Audio IPC thread: %d (%s)",
512                                                         err, strerror(err));
513                 goto failed;
514         }
515
516         return 0;
517
518 failed:
519         close(sk);
520         return err;
521 }
522
523 static int audio_open(const hw_module_t *module, const char *name,
524                                                         hw_device_t **device)
525 {
526         struct a2dp_audio_dev *a2dp_dev;
527         int err;
528
529         DBG("");
530
531         if (strcmp(name, AUDIO_HARDWARE_INTERFACE)) {
532                 error("audio: interface %s not matching [%s]", name,
533                                                 AUDIO_HARDWARE_INTERFACE);
534                 return -EINVAL;
535         }
536
537         err = audio_ipc_init();
538         if (err)
539                 return -err;
540
541         a2dp_dev = calloc(1, sizeof(struct a2dp_audio_dev));
542         if (!a2dp_dev)
543                 return -ENOMEM;
544
545         a2dp_dev->dev.common.version = AUDIO_DEVICE_API_VERSION_CURRENT;
546         a2dp_dev->dev.common.module = (struct hw_module_t *) module;
547         a2dp_dev->dev.common.close = audio_close;
548
549         a2dp_dev->dev.init_check = audio_init_check;
550         a2dp_dev->dev.set_voice_volume = audio_set_voice_volume;
551         a2dp_dev->dev.set_master_volume = audio_set_master_volume;
552         a2dp_dev->dev.set_mode = audio_set_mode;
553         a2dp_dev->dev.set_mic_mute = audio_set_mic_mute;
554         a2dp_dev->dev.get_mic_mute = audio_get_mic_mute;
555         a2dp_dev->dev.set_parameters = audio_set_parameters;
556         a2dp_dev->dev.get_parameters = audio_get_parameters;
557         a2dp_dev->dev.get_input_buffer_size = audio_get_input_buffer_size;
558         a2dp_dev->dev.open_output_stream = audio_open_output_stream;
559         a2dp_dev->dev.close_output_stream = audio_close_output_stream;
560         a2dp_dev->dev.open_input_stream = audio_open_input_stream;
561         a2dp_dev->dev.close_input_stream = audio_close_input_stream;
562         a2dp_dev->dev.dump = audio_dump;
563
564         /* Note that &a2dp_dev->dev.common is the same pointer as a2dp_dev.
565          * This results from the structure of following structs:a2dp_audio_dev,
566          * audio_hw_device. We will rely on this later in the code.*/
567         *device = &a2dp_dev->dev.common;
568
569         return 0;
570 }
571
572 static struct hw_module_methods_t hal_module_methods = {
573         .open = audio_open,
574 };
575
576 struct audio_module HAL_MODULE_INFO_SYM = {
577         .common = {
578         .tag = HARDWARE_MODULE_TAG,
579         .version_major = 1,
580         .version_minor = 0,
581         .id = AUDIO_HARDWARE_MODULE_ID,
582         .name = "A2DP Bluez HW HAL",
583         .author = "Intel Corporation",
584         .methods = &hal_module_methods,
585         },
586 };