blob: 6f4f486d229219621eeea94a8e6e295026f0d282 [file] [log] [blame]
Tim Yaoe8c0d4a2019-11-27 14:47:35 -08001#include <thread>
2#include <mutex>
3#include <cstdlib>
4
5#include <hardware/hardware.h>
6#include <hardware/audio.h>
7#include <pthread.h>
Tim Yaoe8c0d4a2019-11-27 14:47:35 -08008#include <cutils/log.h>
9
10#include <grpc/grpc.h>
11#include <grpcpp/channel.h>
12#include <grpcpp/client_context.h>
13#include <grpcpp/create_channel.h>
14#include <grpcpp/security/credentials.h>
15
16#include "audio_if_client.h"
17#include "audio_client.h"
18
19//#define TRACE_ENTRY() printf("[Client:%s] enter\n", __func__)
20#define TRACE_ENTRY()
21
22static AudioClient *client;
23static int inited = 0;
24static std::mutex client_mutex;
25
26static uint32_t stream_get_sample_rate(const struct audio_stream *stream)
27{
28 TRACE_ENTRY();
29 return client->stream_get_sample_rate(stream);
30}
31
32static size_t stream_get_buffer_size(const struct audio_stream *stream)
33{
34 TRACE_ENTRY();
35 return client->stream_get_buffer_size(stream);
36}
37
38static audio_channel_mask_t stream_get_channels(const struct audio_stream *stream)
39{
40 TRACE_ENTRY();
41 return client->stream_get_channels(stream);
42}
43
44static audio_format_t stream_get_format(const struct audio_stream *stream)
45{
46 TRACE_ENTRY();
47 return client->stream_get_format(stream);
48}
49
50static int stream_standby(struct audio_stream *stream)
51{
52 TRACE_ENTRY();
53 return client->stream_standby(stream);
54}
55
56static int stream_dump(const struct audio_stream *stream, int fd)
57{
58 TRACE_ENTRY();
59 return client->stream_dump(stream, fd);
60}
61
62static audio_devices_t stream_get_device(const struct audio_stream *stream)
63{
64 TRACE_ENTRY();
65 return client->stream_get_device(stream);
66}
67
68static int stream_set_parameters(struct audio_stream *stream, const char *kv_pairs)
69{
70 TRACE_ENTRY();
71 return client->stream_set_parameters(stream, kv_pairs);
72}
73
74static char * stream_get_parameters(const struct audio_stream *stream,
75 const char *keys)
76{
77 TRACE_ENTRY();
78 return client->stream_get_parameters(stream, keys);
79}
80
81static int stream_in_set_gain(struct audio_stream_in *stream, float gain)
82{
83 TRACE_ENTRY();
84 return client->stream_in_set_gain(stream, gain);
85}
86
87static ssize_t stream_in_read(struct audio_stream_in *stream, void* buffer,
88 size_t bytes)
89{
90 TRACE_ENTRY();
91 return client->stream_in_read(stream, buffer, bytes);
92}
93
94static uint32_t stream_in_get_input_frames_lost(struct audio_stream_in *stream)
95{
96 TRACE_ENTRY();
97 return client->stream_in_get_input_frames_lost(stream);
98}
99
100static int stream_in_get_capture_position(const struct audio_stream_in *stream,
101 int64_t *frames, int64_t *time)
102{
103 TRACE_ENTRY();
104 return client->stream_in_get_capture_position(stream, frames, time);
105}
106
107static uint32_t stream_out_get_latency(const struct audio_stream_out *stream)
108{
109 TRACE_ENTRY();
110 return client->stream_out_get_latency(stream);
111}
112
113static int stream_out_set_volume(struct audio_stream_out *stream, float left, float right)
114{
115 TRACE_ENTRY();
116 return client->stream_out_set_volume(stream, left, right);
117}
118
119static ssize_t stream_out_write(struct audio_stream_out *stream, const void* buffer,
120 size_t bytes)
121{
122 TRACE_ENTRY();
123 return client->stream_out_write(stream, buffer, bytes);
124}
125
126static int stream_out_get_render_position(const struct audio_stream_out *stream,
127 uint32_t *dsp_frames)
128{
129 TRACE_ENTRY();
130 return client->stream_out_get_render_position(stream, dsp_frames);
131}
132
133static int stream_out_get_next_write_timestamp(const struct audio_stream_out *stream,
134 int64_t *timestamp)
135{
136 TRACE_ENTRY();
137 return client->stream_out_get_next_write_timestamp(stream, timestamp);
138}
139
140static int stream_out_pause(struct audio_stream_out* stream)
141{
142 TRACE_ENTRY();
143 return client->stream_out_pause(stream);
144}
145
146static int stream_out_resume(struct audio_stream_out* stream)
147{
148 TRACE_ENTRY();
149 return client->stream_out_resume(stream);
150}
151
152static int stream_out_flush(struct audio_stream_out* stream)
153{
154 TRACE_ENTRY();
155 return client->stream_out_flush(stream);
156}
157
158static int stream_out_get_presentation_position(const struct audio_stream_out *stream,
159 uint64_t *frames, struct timespec *timestamp)
160{
161 TRACE_ENTRY();
162 return client->stream_out_get_presentation_position(stream, frames, timestamp);
163}
164
165struct audio_stream_in stream_in_template = {
166 .common = {
167 .get_sample_rate = stream_get_sample_rate,
168 .set_sample_rate = NULL,
169 .get_buffer_size = stream_get_buffer_size,
170 .get_channels = stream_get_channels,
171 .get_format = stream_get_format,
172 .set_format = NULL,
173 .standby = stream_standby,
174 .dump = stream_dump,
175 .get_device = stream_get_device,
176 .set_device = NULL,
177 .set_parameters = stream_set_parameters,
178 .get_parameters = stream_get_parameters,
179 .add_audio_effect = NULL,
180 .remove_audio_effect = NULL
181 },
182 .set_gain = stream_in_set_gain,
183 .read = stream_in_read,
184 .get_input_frames_lost = stream_in_get_input_frames_lost,
185 .get_capture_position = stream_in_get_capture_position,
186 .start = NULL,
187 .stop = NULL,
188 .create_mmap_buffer = NULL,
189 .get_mmap_position = NULL,
190 .get_active_microphones = NULL,
xingri.gaob6a384b2023-10-19 07:08:48 +0000191 .set_microphone_direction = NULL,
192 .set_microphone_field_dimension = NULL,
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800193 .update_sink_metadata = NULL
194};
195
196struct audio_stream_out stream_out_template = {
197 .common = {
198 .get_sample_rate = stream_get_sample_rate,
199 .set_sample_rate = NULL,
200 .get_buffer_size = stream_get_buffer_size,
201 .get_channels = stream_get_channels,
202 .get_format = stream_get_format,
203 .set_format = NULL,
204 .standby = stream_standby,
205 .dump = stream_dump,
206 .get_device = stream_get_device,
207 .set_device = NULL,
208 .set_parameters = stream_set_parameters,
209 .get_parameters = stream_get_parameters,
210 .add_audio_effect = NULL,
211 .remove_audio_effect = NULL
212 },
213 .get_latency = stream_out_get_latency,
214 .set_volume = stream_out_set_volume,
215 .write = stream_out_write,
216 .get_render_position = stream_out_get_render_position,
217 .get_next_write_timestamp = stream_out_get_next_write_timestamp,
218 .set_callback = NULL,
219 .pause = stream_out_pause,
220 .resume = stream_out_resume,
221 .drain = NULL,
222 .flush = stream_out_flush,
223 .get_presentation_position = stream_out_get_presentation_position,
224 .start = NULL,
225 .stop = NULL,
226 .create_mmap_buffer = NULL,
227 .get_mmap_position = NULL,
228 .update_source_metadata = NULL
229};
230
231static int Device_common_close(struct hw_device_t* device)
232{
233 // Server side audio hal device is constructed with
234 // server's life span. Skip Device_common_close for client
235 // The method is only needed when server really wants to exit.
236 // return client->Device_common_close(device);
237 return 0;
238}
239
240static int Device_init_check(const struct audio_hw_device *dev)
241{
242 TRACE_ENTRY();
243 return client->Device_init_check(dev);
244}
245
246static int Device_set_voice_volume(struct audio_hw_device *dev, float volume)
247{
248 TRACE_ENTRY();
249 return client->Device_set_voice_volume(dev, volume);
250}
251
252static int Device_set_master_volume(struct audio_hw_device *dev, float volume)
253{
254 TRACE_ENTRY();
255 return client->Device_set_master_volume(dev, volume);
256}
257
258static int Device_get_master_volume(struct audio_hw_device *dev, float *volume)
259{
260 TRACE_ENTRY();
261 return client->Device_get_master_volume(dev, volume);
262}
263
264static int Device_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
265{
266 TRACE_ENTRY();
267 return client->Device_set_mode(dev, mode);
268}
269
270static int Device_set_mic_mute(struct audio_hw_device *dev, bool state)
271{
272 TRACE_ENTRY();
273 return client->Device_set_mic_mute(dev, state);
274}
275
276static int Device_get_mic_mute(const struct audio_hw_device *dev, bool *state)
277{
278 TRACE_ENTRY();
279 return client->Device_get_mic_mute(dev, state);
280}
281
282static int Device_set_parameters(struct audio_hw_device *dev, const char *kv_pairs)
283{
284 TRACE_ENTRY();
285 return client->Device_set_parameters(dev, kv_pairs);
286}
287
288static char * Device_get_parameters(const struct audio_hw_device *dev,
289 const char *keys)
290{
291 TRACE_ENTRY();
292 return client->Device_get_parameters(dev, keys);
293}
294
295static size_t Device_get_input_buffer_size(const struct audio_hw_device *dev,
296 const struct audio_config *config)
297{
298 TRACE_ENTRY();
299 return client->Device_get_input_buffer_size(dev, config);
300}
301
302static int Device_open_output_stream(struct audio_hw_device *dev,
303 audio_io_handle_t handle,
304 audio_devices_t devices,
305 audio_output_flags_t flags,
306 struct audio_config *config,
307 struct audio_stream_out **stream_out,
308 const char *address)
309{
310 TRACE_ENTRY();
311
312 int r;
313 audio_stream_out_client_t *stream_out_client = (audio_stream_out_client_t *)calloc(1, sizeof(audio_stream_out_client_t));
314 if (!stream_out_client) return -ENOMEM;
315
316 r = client->Device_open_output_stream(dev, handle, devices, flags, config, stream_out_client, address);
317 if (r) {
318 free(stream_out);
319 return r;
320 }
321
322 stream_out_client->stream_out = stream_out_template;
323 *stream_out = &(stream_out_client->stream_out);
yuliang.hu19fdc8d2024-07-29 17:42:10 +0800324 /*coverity[resource_leak]: stream_out_client is free in Device_close_output_stream but not here*/
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800325 return r;
326}
327
328static void Device_close_output_stream(struct audio_hw_device *dev,
329 struct audio_stream_out* stream_out)
330{
331 TRACE_ENTRY();
332
333 client->Device_close_output_stream(dev, stream_out);
334 free(audio_stream_out_to_client(stream_out));
335}
336
337static int Device_open_input_stream(struct audio_hw_device *dev,
338 audio_io_handle_t handle,
339 audio_devices_t devices,
340 struct audio_config *config,
341 struct audio_stream_in **stream_in,
342 audio_input_flags_t flags,
343 const char *address,
344 audio_source_t source)
345{
346 TRACE_ENTRY();
347
348 int r;
349 audio_stream_in_client_t *stream_in_client = (audio_stream_in_client_t *)calloc(1, sizeof(audio_stream_in_client_t));
350 if (!stream_in_client) return -ENOMEM;
351
352 r = client->Device_open_input_stream(dev, handle, devices, config, stream_in_client, flags, address, source);
353 if (r) {
354 free(stream_in_client);
355 return r;
356 }
357
358 stream_in_client->stream_in = stream_in_template;
359 *stream_in = &(stream_in_client->stream_in);
yuliang.hu19fdc8d2024-07-29 17:42:10 +0800360 /*coverity[resource_leak]: stream_in_client is free in Device_close_input_stream but not here*/
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800361 return r;
362}
363
364static void Device_close_input_stream(struct audio_hw_device *dev,
365 struct audio_stream_in *stream_in)
366{
367 TRACE_ENTRY();
368
369 client->Device_close_input_stream(dev, stream_in);
370 free(audio_stream_in_to_client(stream_in));
371}
372
Tim Yaoab2a3a62020-10-29 15:33:55 -0700373static char * Device_dump(const struct audio_hw_device *dev, int fd)
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800374{
375 TRACE_ENTRY();
376
377 return client->Device_dump(dev, fd);
378}
379
380static int Device_set_master_mute(struct audio_hw_device *dev, bool mute)
381{
382 TRACE_ENTRY();
383
384 return client->Device_set_master_mute(dev, mute);
385}
386
387static int Device_get_master_mute(struct audio_hw_device *dev, bool *mute)
388{
389 TRACE_ENTRY();
390
391 return client->Device_get_master_mute(dev, mute);
392}
393
394static int Device_create_audio_patch(struct audio_hw_device *dev,
395 unsigned int num_sources,
396 const struct audio_port_config *sources,
397 unsigned int num_sinks,
398 const struct audio_port_config *sinks,
399 audio_patch_handle_t *handle)
400{
401 TRACE_ENTRY();
402
403 return client->Device_create_audio_patch(dev, num_sources, sources, num_sinks, sinks, handle);
404}
405
406static int Device_release_audio_patch(struct audio_hw_device *dev,
407 audio_patch_handle_t handle)
408{
409 TRACE_ENTRY();
410
411 return client->Device_release_audio_patch(dev, handle);
412}
413
414static int Device_set_audio_port_config(struct audio_hw_device *dev,
415 const struct audio_port_config *config)
416{
417 TRACE_ENTRY();
418
419 return client->Device_set_audio_port_config(dev, config);
420}
421
422static struct hw_module_t hw_module = {
423 .tag = HARDWARE_MODULE_TAG,
424 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
425 .hal_api_version = HARDWARE_HAL_API_VERSION,
426 .id = AUDIO_HARDWARE_MODULE_ID,
427 .name = "aml audio HW HAL",
428 .author = "amlogic, Corp.",
429};
430
431static audio_hw_device_t device = {
432 .common = {
433 .tag = HARDWARE_DEVICE_TAG,
434 .version = AUDIO_DEVICE_API_VERSION_3_0,
435 .module = &hw_module,
436 .reserved = {0},
437 .close = Device_common_close,
438 },
439 .get_supported_devices = NULL,
440 .init_check = Device_init_check,
441 .set_voice_volume = Device_set_voice_volume,
442 .set_master_volume = Device_set_master_volume,
443 .get_master_volume = Device_get_master_volume,
444 .set_mode = Device_set_mode,
445 .set_mic_mute = Device_set_mic_mute,
446 .get_mic_mute = Device_get_mic_mute,
447 .set_parameters = Device_set_parameters,
448 .get_parameters = Device_get_parameters,
449 .get_input_buffer_size = Device_get_input_buffer_size,
450 .open_output_stream = Device_open_output_stream,
451 .close_output_stream = Device_close_output_stream,
452 .open_input_stream = Device_open_input_stream,
453 .close_input_stream = Device_close_input_stream,
454 .get_microphones = NULL,
455 .dump = Device_dump,
456 .set_master_mute = Device_set_master_mute,
457 .get_master_mute = Device_get_master_mute,
458 .create_audio_patch = Device_create_audio_patch,
459 .release_audio_patch = Device_release_audio_patch,
460 .get_audio_port = NULL,
461 .set_audio_port_config = Device_set_audio_port_config,
462};
463
464extern "C" {
465
466int audio_hw_load_interface(audio_hw_device_t **dev)
467{
468 TRACE_ENTRY();
yuliang.hu19fdc8d2024-07-29 17:42:10 +0800469 /*coverity[missing_lock]:printf no need to lock*/
xingri.gao7a09da12024-12-16 10:05:37 +0800470 //printf("PID = %d, inited = %d\n", ::getpid(), inited);
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800471
Tim Yao1b84e362020-08-24 12:51:36 -0700472 const char *url = std::getenv("AUDIO_SERVER_SOCKET");
473
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800474 std::lock_guard<std::mutex> lock(client_mutex);
475
476 if (inited++ > 0) {
477 *dev = &device;
478 return 0;
479 }
480
481 client = new AudioClient(
wei.duc64b06a2022-01-17 16:51:12 +0800482 grpc::CreateChannel((url) ? url : "unix:///tmp/audio_socket",
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800483 grpc::InsecureChannelCredentials()));
484
485 *dev = &device;
486 inited = 1;
487
488 return 0;
489}
490
491void audio_hw_unload_interface(audio_hw_device_t *dev)
492{
493 TRACE_ENTRY();
494
495 std::lock_guard<std::mutex> lock(client_mutex);
496
497 if (--inited == 0) {
498 delete client;
499 client = nullptr;
500 }
501}
502
cheng tong7d907882020-09-04 18:53:04 +0800503int audio_effect_set_parameters(aml_audio_effect_type_e type, effect_param_t *param)
504{
505 TRACE_ENTRY();
506
507 std::lock_guard<std::mutex> lock(client_mutex);
508
509 if (type >= AML_EFFECT_MAX || type < 0)
510 return -1;
511
512 if (param == NULL || param->psize == 0 || param->vsize == 0) {
513 return -1;
514 }
515
516 return client->Effect_set_parameters(type, param);
517}
518
519int audio_effect_get_parameters(aml_audio_effect_type_e type, effect_param_t *param)
520{
521 TRACE_ENTRY();
522
523 std::lock_guard<std::mutex> lock(client_mutex);
524
525 if (type >= AML_EFFECT_MAX || type < 0)
526 return -1;
527
528 if (param == NULL || param->psize == 0 || param->vsize == 0) {
529 return -1;
530 }
531
532 return client->Effect_get_parameters(type, param);
533}
534
yayun.shi36127aa2024-11-19 16:48:57 +0800535int audio_hw_register_server_died_callback(audio_hw_device_t *dev, void *callback)
536{
537 return -1;
538}
539
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800540}