blob: ec6a2ed473905213a23494f2d7cf9214b5ecff24 [file] [log] [blame]
Tim Yaoe8c0d4a2019-11-27 14:47:35 -08001#include <sys/types.h>
2#include <unistd.h>
3#include <sys/stat.h>
4#include <fcntl.h>
5
6#include <boost/interprocess/managed_shared_memory.hpp>
7#include <cstdlib>
8#include <iomanip>
9#include <mutex>
10#include <signal.h>
11
12#define LOG_TAG "audio_server"
13#include <cutils/log.h>
14
15#include <grpc/grpc.h>
16#include <grpcpp/server.h>
17#include <grpcpp/server_builder.h>
18#include <grpcpp/server_context.h>
19#include <grpcpp/security/server_credentials.h>
20#include "audio_if.h"
21#include "audio_service.grpc.pb.h"
22#include "CircularBuffer.h"
23
24using grpc::Server;
25using grpc::ServerBuilder;
26using grpc::ServerContext;
27using grpc::ServerReader;
28using grpc::ServerReaderWriter;
29using grpc::ServerWriter;
30using grpc::Status;
31using audio_service::StatusReturn;
32using audio_service::Volume;
33using audio_service::Mode;
34using audio_service::Mute;
35using audio_service::Kv_pairs;
36using audio_service::Keys;
37using audio_service::Handle;
38using audio_service::OpenOutputStream;
39using audio_service::Stream;
40using audio_service::OpenInputStream;
41using audio_service::CreateAudioPatch;
42using audio_service::AudioPortConfig;
43using audio_service::AudioGainConfig;
44using audio_service::AudioPortConfigDeviceExt;
45using audio_service::AudioPortConfigMixExt;
46using audio_service::AudioPortConfigSessionExt;
47using audio_service::StreamSetParameters;
48using audio_service::StreamGetParameters;
49using audio_service::StreamAudioEffect;
50using audio_service::StreamOutSetVolume;
51using audio_service::StreamReadWrite;
52using audio_service::GetFrameTimestampReturn;
53using audio_service::StreamGain;
54using google::protobuf::Empty;
55
56using namespace boost::interprocess;
57using namespace audio_service;
58
59//#define DEBUG__
60
61#ifdef DEBUG__
62#define TRACE_ENTRY() ALOGI("%s enter\n", __func__)
63#define TRACE_EXIT() ALOGI("%s exit\n", __func__)
64#else
65#define TRACE_ENTRY()
66#define TRACE_EXIT()
67#endif
68
69const int AudioServerShmemSize = 16 * 1024 * 1024;
70
71typedef std::pair<CircularBuffer *, struct audio_stream_out *> streamout_map_t;
72typedef std::pair<CircularBuffer *, struct audio_stream_in *> streamin_map_t;
73
74class AudioServiceImpl final : public AudioService::Service
75{
76 public:
77 explicit AudioServiceImpl(managed_shared_memory &shm)
78 : shm_(shm) {
79 if (audio_hw_load_interface(&dev_) == 0) {
80 //ALOGI(__func__, "[AudioServer] Get audio hal interface successfully.\n");
81 }
82 }
83
84 ~AudioServiceImpl() {
85 if (dev_) {
86 audio_hw_unload_interface(dev_);
87 dev_ = nullptr;
88 }
89 }
90
91 Status Device_common_close(ServerContext* context, const Empty* empty, StatusReturn* response) {
92 TRACE_ENTRY();
93 if (!dev_) return Status::CANCELLED;
94
95 response->set_ret(dev_->common.close(&dev_->common));
96 return Status::OK;
97 }
98
99 Status Device_init_check(ServerContext* context, const Empty* empty, StatusReturn* response) {
100 TRACE_ENTRY();
101 if (!dev_) return Status::CANCELLED;
102
103 response->set_ret(dev_->init_check(dev_));
104 return Status::OK;
105 }
106
107 Status Device_set_voice_volume(ServerContext* context, const Volume* request, StatusReturn* response) {
108 TRACE_ENTRY();
109 if (!dev_) return Status::CANCELLED;
110
111 response->set_ret(dev_->set_voice_volume(dev_, request->vol()));
112 return Status::OK;
113 }
114
115 Status Device_set_master_volume(ServerContext* context, const Volume* request, StatusReturn* response) {
116 TRACE_ENTRY();
117 if (!dev_) return Status::CANCELLED;
118
119 response->set_ret(dev_->set_master_volume(dev_, request->vol()));
120 return Status::OK;
121 }
122
123 Status Device_get_master_volume(ServerContext* context, const Empty* request, StatusReturn* response) {
124 TRACE_ENTRY();
125 if (!dev_) return Status::CANCELLED;
126
127 float vol = 0.0;
128 response->set_ret(dev_->get_master_volume(dev_, &vol));
129 response->set_status_float(vol);
130 return Status::OK;
131 }
132
133 Status Device_set_mode(ServerContext* context, const Mode* request, StatusReturn* response) {
134 TRACE_ENTRY();
135 if (!dev_) return Status::CANCELLED;
136
137 response->set_ret(dev_->set_mode(dev_, (audio_mode_t)(request->mode())));
138 return Status::OK;
139 }
140
141 Status Device_set_mic_mute(ServerContext* context, const Mute* request, StatusReturn* response) {
142 TRACE_ENTRY();
143 if (!dev_) return Status::CANCELLED;
144
145 response->set_ret(dev_->set_mic_mute(dev_, request->mute()));
146 return Status::OK;
147 }
148
149 Status Device_get_mic_mute(ServerContext* context, const Empty* request, StatusReturn* response) {
150 TRACE_ENTRY();
151 if (!dev_) return Status::CANCELLED;
152
153 bool mute = false;
154 response->set_ret(dev_->get_mic_mute(dev_, &mute));
155 response->set_status_bool(mute);
156 return Status::OK;
157 }
158
159 Status Device_set_parameters(ServerContext* context, const Kv_pairs* request, StatusReturn* response) {
160 TRACE_ENTRY();
161 if (!dev_) return Status::CANCELLED;
162
163 response->set_ret(dev_->set_parameters(dev_, request->params().c_str()));
164 return Status::OK;
165 }
166
167 Status Device_get_parameters(ServerContext* context, const Keys* request, StatusReturn* response) {
168 TRACE_ENTRY();
169 if (!dev_) return Status::CANCELLED;
170
171 char *param = dev_->get_parameters(dev_, request->keys().c_str());
172 response->set_ret(param ? 0 : -1);
173 response->set_status_string(std::string(param));
174
175 // param is heap allocated and need free in behalf of client
176 free(param);
177
178 return Status::OK;
179 }
180
181 Status Device_get_input_buffer_size(ServerContext* context, const AudioConfig* request, StatusReturn* response) {
182 TRACE_ENTRY();
183 if (!dev_) return Status::CANCELLED;
184
185 struct audio_config config;
186 config.sample_rate = request->sample_rate();
187 config.channel_mask = request->channel_mask();
188 config.format = (audio_format_t)(request->format());
189 config.frame_count = request->frame_count();
190
191 response->set_ret(dev_->get_input_buffer_size(dev_, &config));
192 return Status::OK;
193 }
194
195 Status Device_open_output_stream(ServerContext* context, const OpenOutputStream* request, StatusReturn* response) {
196 TRACE_ENTRY();
197 if (!dev_) return Status::CANCELLED;
198
199 struct audio_stream_out *stream = nullptr;
200 struct audio_config config;
201 config.sample_rate = request->config().sample_rate();
202 config.channel_mask = request->config().channel_mask();
203 config.format = (audio_format_t)(request->config().format());
204 config.frame_count = request->config().frame_count();
205
206 streamout_gc_();
207
208 response->set_ret(dev_->open_output_stream(dev_,
209 (audio_io_handle_t)(request->handle()),
210 (audio_devices_t)(request->devices()),
211 (audio_output_flags_t)(request->flags()),
212 &config,
213 &stream,
214 request->address().c_str()));
215
216 if (stream) {
217 CircularBuffer * cb = shm_.find<CircularBuffer>(request->name().c_str()).first;
218 if (cb == nullptr)
219 cb = shm_.construct<CircularBuffer>(request->name().c_str())(shm_, request->size());
220
221 std::lock_guard<std::mutex> lock(map_out_mutex_);
222 streamout_map_.insert(
223 std::pair<const std::string, streamout_map_t>(request->name(), streamout_map_t(cb, stream)));
224 }
225
226 return Status::OK;
227 }
228
229 Status Device_close_output_stream(ServerContext* context, const Stream* request, StatusReturn* response) {
230 TRACE_ENTRY();
231 if (!dev_) return Status::CANCELLED;
232
233 std::map<const std::string, streamout_map_t >::iterator it = streamout_map_.find(request->name());
234 if (it == streamout_map_.end()) return Status::CANCELLED;
235
236 dev_->close_output_stream(dev_, it->second.second);
237
238 if (it->second.first) {
239 shm_.destroy<CircularBuffer>(request->name().c_str());
240 }
241
242 std::lock_guard<std::mutex> lock(map_out_mutex_);
243 streamout_map_.erase(it);
244
245 TRACE_EXIT();
246
247 return Status::OK;
248 }
249
250 Status Device_open_input_stream(ServerContext* context, const OpenInputStream* request, StatusReturn* response) {
251 TRACE_ENTRY();
252 if (!dev_) return Status::CANCELLED;
253
254 struct audio_stream_in *stream = nullptr;
255 struct audio_config config;
256 config.sample_rate = request->config().sample_rate();
257 config.channel_mask = request->config().channel_mask();
258 config.format = (audio_format_t)(request->config().format());
259 config.frame_count = request->config().frame_count();
260
261 streamin_gc_();
262
263 response->set_ret(dev_->open_input_stream(dev_,
264 (audio_io_handle_t)(request->handle()),
265 (audio_devices_t)(request->devices()),
266 &config,
267 &stream,
268 (audio_input_flags_t)(request->flags()),
269 request->address().c_str(),
270 (audio_source_t)(request->source())));
271
272 if (stream) {
273 CircularBuffer * cb = shm_.find<CircularBuffer>(request->name().c_str()).first;
274 if (cb == nullptr)
275 cb = shm_.construct<CircularBuffer>(request->name().c_str())(shm_, request->size());
276
277 std::lock_guard<std::mutex> lock(map_in_mutex_);
278 streamin_map_.insert(
279 std::pair<const std::string, streamin_map_t>(request->name(), streamin_map_t(cb, stream)));
280 }
281
282 return Status::OK;
283 }
284
285 Status Device_close_input_stream(ServerContext* context, const Stream* request, StatusReturn* response) {
286 TRACE_ENTRY();
287 if (!dev_) return Status::CANCELLED;
288
289 std::map<const std::string, streamin_map_t >::iterator it = streamin_map_.find(request->name());
290 if (it == streamin_map_.end()) return Status::CANCELLED;
291
292 dev_->close_input_stream(dev_, it->second.second);
293
294 if (it->second.first) {
295 shm_.destroy<CircularBuffer>(request->name().c_str());
296 }
297
298 std::lock_guard<std::mutex> lock(map_in_mutex_);
299 streamin_map_.erase(it);
300
301 return Status::OK;
302 }
303
304 Status Device_dump(ServerContext* context, const Empty* request, StatusReturn* response) {
305 TRACE_ENTRY();
306 if (!dev_) return Status::CANCELLED;
307
Tim Yaoab2a3a62020-10-29 15:33:55 -0700308 char *param = dev_->dump(dev_, 0);
309 response->set_ret(param ? 0 : -1);
310 response->set_status_string(std::string(param));
311
312 // param is heap allocated and need free
313 free(param);
314
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800315 return Status::OK;
316 }
317
318 Status Device_set_master_mute(ServerContext* context, const Mute* request, StatusReturn* response) {
319 TRACE_ENTRY();
320 if (!dev_) return Status::CANCELLED;
321
322 response->set_ret(dev_->set_master_mute(dev_, request->mute()));
323 return Status::OK;
324 }
325
326 Status Device_get_master_mute(ServerContext* context, const Empty* request, StatusReturn* response) {
327 TRACE_ENTRY();
328 if (!dev_) return Status::CANCELLED;
329
330 bool mute = false;
331 response->set_ret(dev_->get_master_mute(dev_, &mute));
332 response->set_status_bool(mute);
333 return Status::OK;
334 }
335
336 Status Device_create_audio_patch(ServerContext* context, const CreateAudioPatch* request, StatusReturn* response) {
337 TRACE_ENTRY();
338 if (!dev_) return Status::CANCELLED;
339
340 struct audio_port_config *sources, *sinks;
341 unsigned int num_sources = request->sources_size();
342 unsigned int num_sinks = request->sinks_size();
343
344 struct audio_port_config *configs = new struct audio_port_config[num_sources + num_sinks];
345
346 streamout_gc_();
347 streamin_gc_();
348
349 for (int i = 0; i < num_sources + num_sinks; i++) {
350 const AudioPortConfig &config = (i < num_sources) ?
351 request->sources(i) : request->sinks(i - num_sources);
352 configs[i].id = config.id();
353 configs[i].role = (audio_port_role_t)config.role();
354 configs[i].type = (audio_port_type_t)config.type();
355 configs[i].config_mask = config.config_mask();
356 configs[i].sample_rate = config.sample_rate();
357 configs[i].channel_mask = config.channel_mask();
358 configs[i].format = (audio_format_t)config.format();
359
360 // gain
361 configs[i].gain.index = config.gain().index();
362 configs[i].gain.mode = (audio_gain_mode_t)config.gain().mode();
363 configs[i].gain.channel_mask = (audio_channel_mask_t)config.gain().channel_mask();
364 for (int j = 0; j < config.gain().values_size(); j++)
365 configs[i].gain.values[j] = config.gain().values(j);
366 configs[i].gain.ramp_duration_ms = config.gain().ramp_duration_ms();
367
368 if (configs[i].type == AUDIO_PORT_TYPE_DEVICE) {
369 // AudioPortConfigDeviceExt
370 configs[i].ext.device.hw_module = (audio_module_handle_t)config.device().hw_module();
371 configs[i].ext.device.type = (audio_devices_t)config.device().type();
372 strncpy(configs[i].ext.device.address, config.device().address().c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
373 } else if (configs[i].type == AUDIO_PORT_TYPE_MIX) {
374 // AudioPortConfigMixExt
375 configs[i].ext.mix.hw_module = (audio_module_handle_t)config.mix().hw_module();
376 configs[i].ext.mix.handle = (audio_io_handle_t)config.mix().handle();
377 configs[i].ext.mix.usecase.stream = (audio_stream_type_t)config.mix().stream_source();
378 } else if (configs[i].type == AUDIO_PORT_TYPE_SESSION) {
379 // AudioPortConfigSessionExt
380 configs[i].ext.session.session = (audio_session_t)config.session().session();
381 }
382 }
383
384 audio_patch_handle_t handle = (audio_patch_handle_t)(-1);
385 response->set_ret(dev_->create_audio_patch(dev_, num_sources,
386 configs, num_sinks, &configs[num_sources], &handle));
387 response->set_status_32((uint32_t)handle);
388
389 delete [] configs;
390
391 return Status::OK;
392 }
393
394 Status Device_release_audio_patch(ServerContext* context, const Handle* request, StatusReturn* response) {
395 TRACE_ENTRY();
396 if (!dev_) return Status::CANCELLED;
397
398 audio_patch_handle_t handle = (audio_patch_handle_t)(request->handle());
399 response->set_ret(dev_->release_audio_patch(dev_, handle));
400 return Status::OK;
401 }
402
403 Status Device_set_audio_port_config(ServerContext* context, const AudioPortConfig* request, StatusReturn* response) {
404 TRACE_ENTRY();
405 if (!dev_) return Status::CANCELLED;
406
407 struct audio_port_config config;
408
409 config.id = request->id();
410 config.role = (audio_port_role_t)request->role();
411 config.type = (audio_port_type_t)request->type();
412 config.config_mask = request->config_mask();
413 config.sample_rate = request->sample_rate();
414 config.channel_mask = request->channel_mask();
415 config.format = (audio_format_t)request->format();
416
417 // gain
418 config.gain.index = request->gain().index();
419 config.gain.mode = (audio_gain_mode_t)request->gain().mode();
420 config.gain.channel_mask = (audio_channel_mask_t)request->gain().channel_mask();
421 for (int j = 0; j < request->gain().values_size(); j++)
422 config.gain.values[j] = request->gain().values(j);
423 config.gain.ramp_duration_ms = request->gain().ramp_duration_ms();
424
425 if (config.type == AUDIO_PORT_TYPE_DEVICE) {
426 // AudioPortConfigDeviceExt
427 config.ext.device.hw_module = (audio_module_handle_t)request->device().hw_module();
428 config.ext.device.type = (audio_devices_t)request->device().type();
429 strncpy(config.ext.device.address, request->device().address().c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
430 } else if (config.type == AUDIO_PORT_TYPE_MIX) {
431 // AudioPortConfigMixExt
432 config.ext.mix.hw_module = (audio_module_handle_t)request->mix().hw_module();
433 config.ext.mix.handle = (audio_io_handle_t)request->mix().handle();
434 config.ext.mix.usecase.stream = (audio_stream_type_t)request->mix().stream_source();
435 } else if (config.type == AUDIO_PORT_TYPE_SESSION) {
436 // AudioPortConfigSessionExt
437 config.ext.session.session = (audio_session_t)request->session().session();
438 }
439
440 response->set_ret(dev_->set_audio_port_config(dev_, &config));
441 return Status::OK;
442 }
443
444 Status Stream_get_sample_rate(ServerContext* context, const Stream* request, StatusReturn* response) {
445 TRACE_ENTRY();
446 if (!dev_) return Status::CANCELLED;
447
448 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
449 if (stream == nullptr) return Status::CANCELLED;
450
451 response->set_ret(stream->get_sample_rate(stream));
452 return Status::OK;
453 }
454
455 Status Stream_get_buffer_size(ServerContext* context, const Stream* request, StatusReturn* response) {
456 TRACE_ENTRY();
457 if (!dev_) return Status::CANCELLED;
458
459 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
460 if (stream == nullptr) return Status::CANCELLED;
461
462 response->set_ret(stream->get_buffer_size(stream));
463 return Status::OK;
464 }
465
466 Status Stream_get_channels(ServerContext* context, const Stream* request, StatusReturn* response) {
467 TRACE_ENTRY();
468 if (!dev_) return Status::CANCELLED;
469
470 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
471 if (stream == nullptr) return Status::CANCELLED;
472
473 response->set_ret((uint32_t)stream->get_channels(stream));
474 return Status::OK;
475 }
476
477 Status Stream_get_format(ServerContext* context, const Stream* request, StatusReturn* response) {
478 TRACE_ENTRY();
479 if (!dev_) return Status::CANCELLED;
480
481 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
482 if (stream == nullptr) return Status::CANCELLED;
483
484 response->set_ret((uint32_t)stream->get_format(stream));
485 return Status::OK;
486 }
487
488 Status Stream_standby(ServerContext* context, const Stream* request, StatusReturn* response) {
489 TRACE_ENTRY();
490 if (!dev_) return Status::CANCELLED;
491
492 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
493 if (stream == nullptr) return Status::CANCELLED;
494
495 response->set_ret((uint32_t)stream->standby(stream));
496 return Status::OK;
497 }
498
499 Status Stream_get_device(ServerContext* context, const Stream* request, StatusReturn* response) {
500 TRACE_ENTRY();
501 if (!dev_) return Status::CANCELLED;
502
503 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
504 if (stream == nullptr) return Status::CANCELLED;
505
506 response->set_ret((uint32_t)stream->get_device(stream));
507 return Status::OK;
508 }
509
510 Status Stream_set_parameters(ServerContext* context, const StreamSetParameters* request, StatusReturn* response) {
511 TRACE_ENTRY();
512 if (!dev_) return Status::CANCELLED;
513
514 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
515 if (stream == nullptr) return Status::CANCELLED;
516
517 const char *kv_pairs = request->kv_pairs().c_str();
518 response->set_ret(stream->set_parameters(stream, kv_pairs));
519 return Status::OK;
520 }
521
522 Status Stream_get_parameters(ServerContext* context, const StreamGetParameters* request, StatusReturn* response) {
523 TRACE_ENTRY();
524 if (!dev_) return Status::CANCELLED;
525
526 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
527 if (stream == nullptr) return Status::CANCELLED;
528
529 char *param = stream->get_parameters(stream, request->keys().c_str());
530 response->set_ret(param ? 0 : -1);
531 response->set_status_string(std::string(param));
532
533 // param is heap allocated and need free in behalf of client
534 free(param);
535
536 return Status::OK;
537 }
538
539 Status StreamOut_get_latency(ServerContext* context, const Stream* request, StatusReturn* response) {
540 TRACE_ENTRY();
541 if (!dev_) return Status::CANCELLED;
542
543 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
544 if (stream == nullptr) return Status::CANCELLED;
545
546 response->set_ret(stream->get_latency(stream));
547 return Status::OK;
548 }
549
550 Status StreamOut_set_volume(ServerContext* context, const StreamOutSetVolume* request, StatusReturn* response) {
551 TRACE_ENTRY();
552 if (!dev_) return Status::CANCELLED;
553
554 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
555 if (stream == nullptr) return Status::CANCELLED;
556
557 response->set_ret(stream->set_volume(stream, request->left(), request->right()));
558 return Status::OK;
559 }
560
561 Status StreamOut_write(ServerContext* context, const StreamReadWrite* request, StatusReturn* response) {
562 TRACE_ENTRY();
563 if (!dev_) return Status::CANCELLED;
564
565 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
566 if (stream == nullptr) return Status::CANCELLED;
567
568 CircularBuffer *cb = shm_.find<CircularBuffer>(request->name().c_str()).first;
569 response->set_ret(stream->write(stream, cb->start_ptr(shm_), request->size()));
570 return Status::OK;
571 }
572
573 Status StreamOut_get_render_position(ServerContext* context, const Stream* request, StatusReturn* response) {
574 TRACE_ENTRY();
575 if (!dev_) return Status::CANCELLED;
576
577 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
578 if (stream == nullptr) return Status::CANCELLED;
579
580 uint32_t dsp_frames = 0;
581 response->set_ret(stream->get_render_position(stream, &dsp_frames));
582 response->set_status_32(dsp_frames);
583 return Status::OK;
584 }
585
586 Status StreamOut_get_next_write_timestamp(ServerContext* context, const Stream* request, StatusReturn* response) {
587 TRACE_ENTRY();
588 if (!dev_) return Status::CANCELLED;
589
590 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
591 if (stream == nullptr) return Status::CANCELLED;
592
593 int64_t timestamp = 0;
594 response->set_ret(stream->get_next_write_timestamp(stream, &timestamp));
595 response->set_status_64(timestamp);
596 return Status::OK;
597 }
598
599 Status StreamOut_pause(ServerContext* context, const Stream* request, StatusReturn* response) {
600 TRACE_ENTRY();
601 if (!dev_) return Status::CANCELLED;
602
603 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
604 if (stream == nullptr) return Status::CANCELLED;
605
606 response->set_ret(stream->pause(stream));
607 return Status::OK;
608 }
609
610 Status StreamOut_resume(ServerContext* context, const Stream* request, StatusReturn* response) {
611 TRACE_ENTRY();
612 if (!dev_) return Status::CANCELLED;
613
614 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
615 if (stream == nullptr) return Status::CANCELLED;
616
617 response->set_ret(stream->resume(stream));
618 return Status::OK;
619 }
620
621 Status StreamOut_flush(ServerContext* context, const Stream* request, StatusReturn* response) {
622 TRACE_ENTRY();
623 if (!dev_) return Status::CANCELLED;
624
625 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
626 if (stream == nullptr) return Status::CANCELLED;
627
628 response->set_ret(stream->flush(stream));
629 return Status::OK;
630 }
631
632 Status StreamOut_get_presentation_position(ServerContext* context, const Stream* request, GetFrameTimestampReturn* response) {
633 TRACE_ENTRY();
634 if (!dev_) return Status::CANCELLED;
635
636 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
637 if (stream == nullptr) return Status::CANCELLED;
638
639 uint64_t frames = 0;
640 struct timespec timestamp;
641 response->set_ret(stream->get_presentation_position(stream, &frames, &timestamp));
642 response->set_frames(frames);
643 response->mutable_timestamp()->set_seconds((int64_t)timestamp.tv_sec);
644 response->mutable_timestamp()->set_nanos(timestamp.tv_nsec);
645 return Status::OK;
646 }
647
648 Status StreamIn_set_gain(ServerContext* context, const StreamGain* request, StatusReturn* response) {
649 TRACE_ENTRY();
650 if (!dev_) return Status::CANCELLED;
651
652 struct audio_stream_in *stream = find_streamin(request->name(), streamin_map_);
653 if (stream == nullptr) return Status::CANCELLED;
654
655 response->set_ret(stream->set_gain(stream, request->gain()));
656 return Status::OK;
657 }
658
659 Status StreamIn_read(ServerContext* context, const StreamReadWrite* request, StatusReturn* response) {
660 TRACE_ENTRY();
661 if (!dev_) return Status::CANCELLED;
662
663 struct audio_stream_in *stream = find_streamin(request->name(), streamin_map_);
664 if (stream == nullptr) return Status::CANCELLED;
665
666 CircularBuffer *cb = shm_.find<CircularBuffer>(request->name().c_str()).first;
667 response->set_ret(stream->read(stream, cb->start_ptr(shm_), std::min(request->size(), cb->capacity())));
668 return Status::OK;
669 }
670
671 Status StreamIn_get_input_frames_lost(ServerContext* context, const Stream* request, StatusReturn* response) {
672 TRACE_ENTRY();
673 if (!dev_) return Status::CANCELLED;
674
675 struct audio_stream_in *stream = find_streamin(request->name(), streamin_map_);
676 if (stream == nullptr) return Status::CANCELLED;
677
678 response->set_ret(stream->get_input_frames_lost(stream));
679 return Status::OK;
680 }
681
682 Status StreamIn_get_capture_position(ServerContext* context, const Stream* request, GetCapturePositionReturn* response) {
683 TRACE_ENTRY();
684 if (!dev_) return Status::CANCELLED;
685
686 struct audio_stream_in *stream = find_streamin(request->name(), streamin_map_);
687 if (stream == nullptr) return Status::CANCELLED;
688
689 int64_t frames = 0;
690 int64_t time = 0;
691 response->set_ret(stream->get_capture_position(stream, &frames, &time));
692 response->set_frames(frames);
693 response->set_time(time);
694
695 return Status::OK;
696 }
697
698 Status Service_ping(ServerContext* context, const Empty* empty, StatusReturn* response) {
699 TRACE_ENTRY();
700 response->set_status_32(0);
701 return Status::OK;
702 }
703
704 private:
705 void streamout_gc_()
706 {
707 std::lock_guard<std::mutex> lock_out(map_out_mutex_);
708 for (std::map<const std::string, streamout_map_t >::iterator it = streamout_map_.begin(); it != streamout_map_.end(); ) {
709 int pid, seq;
710 bool need_close = false;
711
712 if (sscanf(it->first.c_str(), "%d-%d", &pid, &seq) == 2) {
713 printf("!!!! found pid = %d\n", pid);
714 // Garbage collect streams when PID does not exists.
715 // It happens when client side crashed, or the client
716 // side does not have the right sequence to close opened streams.
717 if ((kill(pid, 0) == -1) && (errno == ESRCH)) {
718 need_close = true;
719 }
720 }
721 if (need_close) {
722 dev_->close_output_stream(dev_, it->second.second);
723 if (it->second.first) {
724 shm_.destroy<CircularBuffer>(it->first.c_str());
725 }
726 streamout_map_.erase(it++);
727 } else {
728 ++it;
729 }
730 }
731 }
732
733 void streamin_gc_()
734 {
735 std::lock_guard<std::mutex> lock_out(map_in_mutex_);
736 for (std::map<const std::string, streamin_map_t >::iterator it = streamin_map_.begin(); it != streamin_map_.end(); ) {
737 int pid, seq;
738 bool need_close = false;
739
740 if (sscanf(it->first.c_str(), "%d-%d", &pid, &seq) == 2) {
741 // Garbage collect streams when PID does not exists.
742 // It happens when client side crashed, or the client
743 // side does not have the right sequence to close opened streams.
744 if (kill(pid, 0) == ESRCH) {
745 need_close = true;
746 }
747 }
748 if (need_close) {
749 dev_->close_input_stream(dev_, it->second.second);
750 streamin_map_.erase(it++);
751 } else {
752 ++it;
753 }
754 }
755 }
756
757 struct audio_stream *find_stream(std::string name,
758 std::map<const std::string, streamout_map_t> &map_out,
759 std::map<const std::string, streamin_map_t> &map_in)
760 {
761 std::lock_guard<std::mutex> lock_out(map_out_mutex_);
762 std::map<const std::string, streamout_map_t >::iterator it_out = map_out.find(name);
763 if (it_out != map_out.end()) {
764 return &it_out->second.second->common;
765 }
766
767 std::lock_guard<std::mutex> lock_in(map_in_mutex_);
768 std::map<const std::string, streamin_map_t >::iterator it_in = map_in.find(name);
769 if (it_in != map_in.end()) {
770 return &it_in->second.second->common;
771 }
772
773 return nullptr;
774 }
775
776 struct audio_stream_out *find_streamout(std::string name,
777 std::map<const std::string, streamout_map_t> &map_out)
778 {
779 std::lock_guard<std::mutex> lock(map_out_mutex_);
780 std::map<const std::string, streamout_map_t >::iterator it = map_out.find(name);
781 if (it != map_out.end()) {
782 return it->second.second;
783 }
784
785 return nullptr;
786 }
787
788 struct audio_stream_in *find_streamin(std::string name,
789 std::map<const std::string, streamin_map_t> &map_in)
790 {
791 std::lock_guard<std::mutex> lock(map_in_mutex_);
792 std::map<const std::string, streamin_map_t >::iterator it = map_in.find(name);
793 if (it != map_in.end()) {
794 return it->second.second;
795 }
796
797 return nullptr;
798 }
799
800 managed_shared_memory &shm_;
801
802 /* audio hal interface */
803 struct audio_hw_device *dev_;
804 static std::mutex map_in_mutex_;
805 static std::mutex map_out_mutex_;
806 std::map<const std::string, streamout_map_t > streamout_map_;
807 std::map<const std::string, streamin_map_t > streamin_map_;
808};
809
810std::mutex AudioServiceImpl::map_out_mutex_;
811std::mutex AudioServiceImpl::map_in_mutex_;
812
813void RunServer(managed_shared_memory& shm)
814{
Tim Yao1b84e362020-08-24 12:51:36 -0700815 const char *url = std::getenv("AUDIO_SERVER_SOCKET");
816 std::string server_address("unix:///opt/audio_socket");
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800817 AudioServiceImpl service(shm);
Tim Yao1b84e362020-08-24 12:51:36 -0700818 if (url) {
819 server_address = url;
820 }
Tim Yaoe8c0d4a2019-11-27 14:47:35 -0800821 ServerBuilder builder;
822 builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
823 builder.RegisterService(&service);
824 std::unique_ptr<Server> server(builder.BuildAndStart());
825 std::cout << "[AudioServer] listening on " << server_address << std::endl;
826 server->Wait();
827}
828
829static int daemonize()
830{
831 int fd_pid;
832 const char pidfile[] = "/var/run/audio_server.pid";
833 char pid[10];
834
835 fd_pid = open(pidfile, O_RDWR|O_CREAT, 0600);
836 if (fd_pid == -1) {
837 fprintf(stderr, "Unable to open PID lock file\n");
838 return -1;
839 }
840
841 if (lockf(fd_pid, F_TLOCK, 0) == -1) {
842 fprintf(stderr, "Unable to lock PID file, daemon is existing.\n");
843 return -2;
844 }
845
846 snprintf(pid, sizeof(pid), "%d", getpid());
847 write(fd_pid, pid, strlen(pid));
848
849 return 0;
850}
851
852int main(int argc, char** argv)
853{
854 int r = daemonize();
855 if (r < 0)
856 return r;
857
858 shared_memory_object::remove("AudioServiceShmem");
859 managed_shared_memory shm{open_or_create, "AudioServiceShmem", AudioServerShmemSize};
860
861 RunServer(shm);
862 return 0;
863}