blob: 12556effeb0b6e6b4ff14e87a5d833d50e7cc95e [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
308 response->set_ret(0);
309 // TODO: dump server status
310 response->set_status_string(std::string("dump"));
311 return Status::OK;
312 }
313
314 Status Device_set_master_mute(ServerContext* context, const Mute* request, StatusReturn* response) {
315 TRACE_ENTRY();
316 if (!dev_) return Status::CANCELLED;
317
318 response->set_ret(dev_->set_master_mute(dev_, request->mute()));
319 return Status::OK;
320 }
321
322 Status Device_get_master_mute(ServerContext* context, const Empty* request, StatusReturn* response) {
323 TRACE_ENTRY();
324 if (!dev_) return Status::CANCELLED;
325
326 bool mute = false;
327 response->set_ret(dev_->get_master_mute(dev_, &mute));
328 response->set_status_bool(mute);
329 return Status::OK;
330 }
331
332 Status Device_create_audio_patch(ServerContext* context, const CreateAudioPatch* request, StatusReturn* response) {
333 TRACE_ENTRY();
334 if (!dev_) return Status::CANCELLED;
335
336 struct audio_port_config *sources, *sinks;
337 unsigned int num_sources = request->sources_size();
338 unsigned int num_sinks = request->sinks_size();
339
340 struct audio_port_config *configs = new struct audio_port_config[num_sources + num_sinks];
341
342 streamout_gc_();
343 streamin_gc_();
344
345 for (int i = 0; i < num_sources + num_sinks; i++) {
346 const AudioPortConfig &config = (i < num_sources) ?
347 request->sources(i) : request->sinks(i - num_sources);
348 configs[i].id = config.id();
349 configs[i].role = (audio_port_role_t)config.role();
350 configs[i].type = (audio_port_type_t)config.type();
351 configs[i].config_mask = config.config_mask();
352 configs[i].sample_rate = config.sample_rate();
353 configs[i].channel_mask = config.channel_mask();
354 configs[i].format = (audio_format_t)config.format();
355
356 // gain
357 configs[i].gain.index = config.gain().index();
358 configs[i].gain.mode = (audio_gain_mode_t)config.gain().mode();
359 configs[i].gain.channel_mask = (audio_channel_mask_t)config.gain().channel_mask();
360 for (int j = 0; j < config.gain().values_size(); j++)
361 configs[i].gain.values[j] = config.gain().values(j);
362 configs[i].gain.ramp_duration_ms = config.gain().ramp_duration_ms();
363
364 if (configs[i].type == AUDIO_PORT_TYPE_DEVICE) {
365 // AudioPortConfigDeviceExt
366 configs[i].ext.device.hw_module = (audio_module_handle_t)config.device().hw_module();
367 configs[i].ext.device.type = (audio_devices_t)config.device().type();
368 strncpy(configs[i].ext.device.address, config.device().address().c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
369 } else if (configs[i].type == AUDIO_PORT_TYPE_MIX) {
370 // AudioPortConfigMixExt
371 configs[i].ext.mix.hw_module = (audio_module_handle_t)config.mix().hw_module();
372 configs[i].ext.mix.handle = (audio_io_handle_t)config.mix().handle();
373 configs[i].ext.mix.usecase.stream = (audio_stream_type_t)config.mix().stream_source();
374 } else if (configs[i].type == AUDIO_PORT_TYPE_SESSION) {
375 // AudioPortConfigSessionExt
376 configs[i].ext.session.session = (audio_session_t)config.session().session();
377 }
378 }
379
380 audio_patch_handle_t handle = (audio_patch_handle_t)(-1);
381 response->set_ret(dev_->create_audio_patch(dev_, num_sources,
382 configs, num_sinks, &configs[num_sources], &handle));
383 response->set_status_32((uint32_t)handle);
384
385 delete [] configs;
386
387 return Status::OK;
388 }
389
390 Status Device_release_audio_patch(ServerContext* context, const Handle* request, StatusReturn* response) {
391 TRACE_ENTRY();
392 if (!dev_) return Status::CANCELLED;
393
394 audio_patch_handle_t handle = (audio_patch_handle_t)(request->handle());
395 response->set_ret(dev_->release_audio_patch(dev_, handle));
396 return Status::OK;
397 }
398
399 Status Device_set_audio_port_config(ServerContext* context, const AudioPortConfig* request, StatusReturn* response) {
400 TRACE_ENTRY();
401 if (!dev_) return Status::CANCELLED;
402
403 struct audio_port_config config;
404
405 config.id = request->id();
406 config.role = (audio_port_role_t)request->role();
407 config.type = (audio_port_type_t)request->type();
408 config.config_mask = request->config_mask();
409 config.sample_rate = request->sample_rate();
410 config.channel_mask = request->channel_mask();
411 config.format = (audio_format_t)request->format();
412
413 // gain
414 config.gain.index = request->gain().index();
415 config.gain.mode = (audio_gain_mode_t)request->gain().mode();
416 config.gain.channel_mask = (audio_channel_mask_t)request->gain().channel_mask();
417 for (int j = 0; j < request->gain().values_size(); j++)
418 config.gain.values[j] = request->gain().values(j);
419 config.gain.ramp_duration_ms = request->gain().ramp_duration_ms();
420
421 if (config.type == AUDIO_PORT_TYPE_DEVICE) {
422 // AudioPortConfigDeviceExt
423 config.ext.device.hw_module = (audio_module_handle_t)request->device().hw_module();
424 config.ext.device.type = (audio_devices_t)request->device().type();
425 strncpy(config.ext.device.address, request->device().address().c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
426 } else if (config.type == AUDIO_PORT_TYPE_MIX) {
427 // AudioPortConfigMixExt
428 config.ext.mix.hw_module = (audio_module_handle_t)request->mix().hw_module();
429 config.ext.mix.handle = (audio_io_handle_t)request->mix().handle();
430 config.ext.mix.usecase.stream = (audio_stream_type_t)request->mix().stream_source();
431 } else if (config.type == AUDIO_PORT_TYPE_SESSION) {
432 // AudioPortConfigSessionExt
433 config.ext.session.session = (audio_session_t)request->session().session();
434 }
435
436 response->set_ret(dev_->set_audio_port_config(dev_, &config));
437 return Status::OK;
438 }
439
440 Status Stream_get_sample_rate(ServerContext* context, const Stream* request, StatusReturn* response) {
441 TRACE_ENTRY();
442 if (!dev_) return Status::CANCELLED;
443
444 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
445 if (stream == nullptr) return Status::CANCELLED;
446
447 response->set_ret(stream->get_sample_rate(stream));
448 return Status::OK;
449 }
450
451 Status Stream_get_buffer_size(ServerContext* context, const Stream* request, StatusReturn* response) {
452 TRACE_ENTRY();
453 if (!dev_) return Status::CANCELLED;
454
455 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
456 if (stream == nullptr) return Status::CANCELLED;
457
458 response->set_ret(stream->get_buffer_size(stream));
459 return Status::OK;
460 }
461
462 Status Stream_get_channels(ServerContext* context, const Stream* request, StatusReturn* response) {
463 TRACE_ENTRY();
464 if (!dev_) return Status::CANCELLED;
465
466 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
467 if (stream == nullptr) return Status::CANCELLED;
468
469 response->set_ret((uint32_t)stream->get_channels(stream));
470 return Status::OK;
471 }
472
473 Status Stream_get_format(ServerContext* context, const Stream* request, StatusReturn* response) {
474 TRACE_ENTRY();
475 if (!dev_) return Status::CANCELLED;
476
477 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
478 if (stream == nullptr) return Status::CANCELLED;
479
480 response->set_ret((uint32_t)stream->get_format(stream));
481 return Status::OK;
482 }
483
484 Status Stream_standby(ServerContext* context, const Stream* request, StatusReturn* response) {
485 TRACE_ENTRY();
486 if (!dev_) return Status::CANCELLED;
487
488 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
489 if (stream == nullptr) return Status::CANCELLED;
490
491 response->set_ret((uint32_t)stream->standby(stream));
492 return Status::OK;
493 }
494
495 Status Stream_get_device(ServerContext* context, const Stream* request, StatusReturn* response) {
496 TRACE_ENTRY();
497 if (!dev_) return Status::CANCELLED;
498
499 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
500 if (stream == nullptr) return Status::CANCELLED;
501
502 response->set_ret((uint32_t)stream->get_device(stream));
503 return Status::OK;
504 }
505
506 Status Stream_set_parameters(ServerContext* context, const StreamSetParameters* request, StatusReturn* response) {
507 TRACE_ENTRY();
508 if (!dev_) return Status::CANCELLED;
509
510 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
511 if (stream == nullptr) return Status::CANCELLED;
512
513 const char *kv_pairs = request->kv_pairs().c_str();
514 response->set_ret(stream->set_parameters(stream, kv_pairs));
515 return Status::OK;
516 }
517
518 Status Stream_get_parameters(ServerContext* context, const StreamGetParameters* request, StatusReturn* response) {
519 TRACE_ENTRY();
520 if (!dev_) return Status::CANCELLED;
521
522 struct audio_stream *stream = find_stream(request->name(), streamout_map_, streamin_map_);
523 if (stream == nullptr) return Status::CANCELLED;
524
525 char *param = stream->get_parameters(stream, request->keys().c_str());
526 response->set_ret(param ? 0 : -1);
527 response->set_status_string(std::string(param));
528
529 // param is heap allocated and need free in behalf of client
530 free(param);
531
532 return Status::OK;
533 }
534
535 Status StreamOut_get_latency(ServerContext* context, const Stream* request, StatusReturn* response) {
536 TRACE_ENTRY();
537 if (!dev_) return Status::CANCELLED;
538
539 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
540 if (stream == nullptr) return Status::CANCELLED;
541
542 response->set_ret(stream->get_latency(stream));
543 return Status::OK;
544 }
545
546 Status StreamOut_set_volume(ServerContext* context, const StreamOutSetVolume* request, StatusReturn* response) {
547 TRACE_ENTRY();
548 if (!dev_) return Status::CANCELLED;
549
550 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
551 if (stream == nullptr) return Status::CANCELLED;
552
553 response->set_ret(stream->set_volume(stream, request->left(), request->right()));
554 return Status::OK;
555 }
556
557 Status StreamOut_write(ServerContext* context, const StreamReadWrite* request, StatusReturn* response) {
558 TRACE_ENTRY();
559 if (!dev_) return Status::CANCELLED;
560
561 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
562 if (stream == nullptr) return Status::CANCELLED;
563
564 CircularBuffer *cb = shm_.find<CircularBuffer>(request->name().c_str()).first;
565 response->set_ret(stream->write(stream, cb->start_ptr(shm_), request->size()));
566 return Status::OK;
567 }
568
569 Status StreamOut_get_render_position(ServerContext* context, const Stream* request, StatusReturn* response) {
570 TRACE_ENTRY();
571 if (!dev_) return Status::CANCELLED;
572
573 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
574 if (stream == nullptr) return Status::CANCELLED;
575
576 uint32_t dsp_frames = 0;
577 response->set_ret(stream->get_render_position(stream, &dsp_frames));
578 response->set_status_32(dsp_frames);
579 return Status::OK;
580 }
581
582 Status StreamOut_get_next_write_timestamp(ServerContext* context, const Stream* request, StatusReturn* response) {
583 TRACE_ENTRY();
584 if (!dev_) return Status::CANCELLED;
585
586 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
587 if (stream == nullptr) return Status::CANCELLED;
588
589 int64_t timestamp = 0;
590 response->set_ret(stream->get_next_write_timestamp(stream, &timestamp));
591 response->set_status_64(timestamp);
592 return Status::OK;
593 }
594
595 Status StreamOut_pause(ServerContext* context, const Stream* request, StatusReturn* response) {
596 TRACE_ENTRY();
597 if (!dev_) return Status::CANCELLED;
598
599 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
600 if (stream == nullptr) return Status::CANCELLED;
601
602 response->set_ret(stream->pause(stream));
603 return Status::OK;
604 }
605
606 Status StreamOut_resume(ServerContext* context, const Stream* request, StatusReturn* response) {
607 TRACE_ENTRY();
608 if (!dev_) return Status::CANCELLED;
609
610 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
611 if (stream == nullptr) return Status::CANCELLED;
612
613 response->set_ret(stream->resume(stream));
614 return Status::OK;
615 }
616
617 Status StreamOut_flush(ServerContext* context, const Stream* request, StatusReturn* response) {
618 TRACE_ENTRY();
619 if (!dev_) return Status::CANCELLED;
620
621 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
622 if (stream == nullptr) return Status::CANCELLED;
623
624 response->set_ret(stream->flush(stream));
625 return Status::OK;
626 }
627
628 Status StreamOut_get_presentation_position(ServerContext* context, const Stream* request, GetFrameTimestampReturn* response) {
629 TRACE_ENTRY();
630 if (!dev_) return Status::CANCELLED;
631
632 struct audio_stream_out *stream = find_streamout(request->name(), streamout_map_);
633 if (stream == nullptr) return Status::CANCELLED;
634
635 uint64_t frames = 0;
636 struct timespec timestamp;
637 response->set_ret(stream->get_presentation_position(stream, &frames, &timestamp));
638 response->set_frames(frames);
639 response->mutable_timestamp()->set_seconds((int64_t)timestamp.tv_sec);
640 response->mutable_timestamp()->set_nanos(timestamp.tv_nsec);
641 return Status::OK;
642 }
643
644 Status StreamIn_set_gain(ServerContext* context, const StreamGain* request, StatusReturn* response) {
645 TRACE_ENTRY();
646 if (!dev_) return Status::CANCELLED;
647
648 struct audio_stream_in *stream = find_streamin(request->name(), streamin_map_);
649 if (stream == nullptr) return Status::CANCELLED;
650
651 response->set_ret(stream->set_gain(stream, request->gain()));
652 return Status::OK;
653 }
654
655 Status StreamIn_read(ServerContext* context, const StreamReadWrite* request, StatusReturn* response) {
656 TRACE_ENTRY();
657 if (!dev_) return Status::CANCELLED;
658
659 struct audio_stream_in *stream = find_streamin(request->name(), streamin_map_);
660 if (stream == nullptr) return Status::CANCELLED;
661
662 CircularBuffer *cb = shm_.find<CircularBuffer>(request->name().c_str()).first;
663 response->set_ret(stream->read(stream, cb->start_ptr(shm_), std::min(request->size(), cb->capacity())));
664 return Status::OK;
665 }
666
667 Status StreamIn_get_input_frames_lost(ServerContext* context, const Stream* request, StatusReturn* response) {
668 TRACE_ENTRY();
669 if (!dev_) return Status::CANCELLED;
670
671 struct audio_stream_in *stream = find_streamin(request->name(), streamin_map_);
672 if (stream == nullptr) return Status::CANCELLED;
673
674 response->set_ret(stream->get_input_frames_lost(stream));
675 return Status::OK;
676 }
677
678 Status StreamIn_get_capture_position(ServerContext* context, const Stream* request, GetCapturePositionReturn* response) {
679 TRACE_ENTRY();
680 if (!dev_) return Status::CANCELLED;
681
682 struct audio_stream_in *stream = find_streamin(request->name(), streamin_map_);
683 if (stream == nullptr) return Status::CANCELLED;
684
685 int64_t frames = 0;
686 int64_t time = 0;
687 response->set_ret(stream->get_capture_position(stream, &frames, &time));
688 response->set_frames(frames);
689 response->set_time(time);
690
691 return Status::OK;
692 }
693
694 Status Service_ping(ServerContext* context, const Empty* empty, StatusReturn* response) {
695 TRACE_ENTRY();
696 response->set_status_32(0);
697 return Status::OK;
698 }
699
700 private:
701 void streamout_gc_()
702 {
703 std::lock_guard<std::mutex> lock_out(map_out_mutex_);
704 for (std::map<const std::string, streamout_map_t >::iterator it = streamout_map_.begin(); it != streamout_map_.end(); ) {
705 int pid, seq;
706 bool need_close = false;
707
708 if (sscanf(it->first.c_str(), "%d-%d", &pid, &seq) == 2) {
709 printf("!!!! found pid = %d\n", pid);
710 // Garbage collect streams when PID does not exists.
711 // It happens when client side crashed, or the client
712 // side does not have the right sequence to close opened streams.
713 if ((kill(pid, 0) == -1) && (errno == ESRCH)) {
714 need_close = true;
715 }
716 }
717 if (need_close) {
718 dev_->close_output_stream(dev_, it->second.second);
719 if (it->second.first) {
720 shm_.destroy<CircularBuffer>(it->first.c_str());
721 }
722 streamout_map_.erase(it++);
723 } else {
724 ++it;
725 }
726 }
727 }
728
729 void streamin_gc_()
730 {
731 std::lock_guard<std::mutex> lock_out(map_in_mutex_);
732 for (std::map<const std::string, streamin_map_t >::iterator it = streamin_map_.begin(); it != streamin_map_.end(); ) {
733 int pid, seq;
734 bool need_close = false;
735
736 if (sscanf(it->first.c_str(), "%d-%d", &pid, &seq) == 2) {
737 // Garbage collect streams when PID does not exists.
738 // It happens when client side crashed, or the client
739 // side does not have the right sequence to close opened streams.
740 if (kill(pid, 0) == ESRCH) {
741 need_close = true;
742 }
743 }
744 if (need_close) {
745 dev_->close_input_stream(dev_, it->second.second);
746 streamin_map_.erase(it++);
747 } else {
748 ++it;
749 }
750 }
751 }
752
753 struct audio_stream *find_stream(std::string name,
754 std::map<const std::string, streamout_map_t> &map_out,
755 std::map<const std::string, streamin_map_t> &map_in)
756 {
757 std::lock_guard<std::mutex> lock_out(map_out_mutex_);
758 std::map<const std::string, streamout_map_t >::iterator it_out = map_out.find(name);
759 if (it_out != map_out.end()) {
760 return &it_out->second.second->common;
761 }
762
763 std::lock_guard<std::mutex> lock_in(map_in_mutex_);
764 std::map<const std::string, streamin_map_t >::iterator it_in = map_in.find(name);
765 if (it_in != map_in.end()) {
766 return &it_in->second.second->common;
767 }
768
769 return nullptr;
770 }
771
772 struct audio_stream_out *find_streamout(std::string name,
773 std::map<const std::string, streamout_map_t> &map_out)
774 {
775 std::lock_guard<std::mutex> lock(map_out_mutex_);
776 std::map<const std::string, streamout_map_t >::iterator it = map_out.find(name);
777 if (it != map_out.end()) {
778 return it->second.second;
779 }
780
781 return nullptr;
782 }
783
784 struct audio_stream_in *find_streamin(std::string name,
785 std::map<const std::string, streamin_map_t> &map_in)
786 {
787 std::lock_guard<std::mutex> lock(map_in_mutex_);
788 std::map<const std::string, streamin_map_t >::iterator it = map_in.find(name);
789 if (it != map_in.end()) {
790 return it->second.second;
791 }
792
793 return nullptr;
794 }
795
796 managed_shared_memory &shm_;
797
798 /* audio hal interface */
799 struct audio_hw_device *dev_;
800 static std::mutex map_in_mutex_;
801 static std::mutex map_out_mutex_;
802 std::map<const std::string, streamout_map_t > streamout_map_;
803 std::map<const std::string, streamin_map_t > streamin_map_;
804};
805
806std::mutex AudioServiceImpl::map_out_mutex_;
807std::mutex AudioServiceImpl::map_in_mutex_;
808
809void RunServer(managed_shared_memory& shm)
810{
811 std::string server_address("0.0.0.0:50051");
812 AudioServiceImpl service(shm);
813
814 ServerBuilder builder;
815 builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
816 builder.RegisterService(&service);
817 std::unique_ptr<Server> server(builder.BuildAndStart());
818 std::cout << "[AudioServer] listening on " << server_address << std::endl;
819 server->Wait();
820}
821
822static int daemonize()
823{
824 int fd_pid;
825 const char pidfile[] = "/var/run/audio_server.pid";
826 char pid[10];
827
828 fd_pid = open(pidfile, O_RDWR|O_CREAT, 0600);
829 if (fd_pid == -1) {
830 fprintf(stderr, "Unable to open PID lock file\n");
831 return -1;
832 }
833
834 if (lockf(fd_pid, F_TLOCK, 0) == -1) {
835 fprintf(stderr, "Unable to lock PID file, daemon is existing.\n");
836 return -2;
837 }
838
839 snprintf(pid, sizeof(pid), "%d", getpid());
840 write(fd_pid, pid, strlen(pid));
841
842 return 0;
843}
844
845int main(int argc, char** argv)
846{
847 int r = daemonize();
848 if (r < 0)
849 return r;
850
851 shared_memory_object::remove("AudioServiceShmem");
852 managed_shared_memory shm{open_or_create, "AudioServiceShmem", AudioServerShmemSize};
853
854 RunServer(shm);
855 return 0;
856}