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