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