blob: d0e958ae0bfc5335af9392c80fb5c7d233ab5a6b [file] [log] [blame]
Tomasz Wiszkowskib34828c2017-09-28 14:03:41 -07001/*
Tomasz Wiszkowskibbf8c0b2017-09-28 14:23:06 -07002 * Copyright (C) 2017 The Android Open Source Project
Tomasz Wiszkowskib34828c2017-09-28 14:03:41 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Tomasz Wiszkowskibbf8c0b2017-09-28 14:23:06 -070016#include "guest/commands/audio/audio_hal.h"
Tomasz Wiszkowskib34828c2017-09-28 14:03:41 -070017
18#include <stdio.h>
19#include <stdlib.h>
20#include <sys/time.h>
21#include <fcntl.h>
22
23extern "C" {
24#include <cutils/str_parms.h>
25}
26
Tomasz Wiszkowskibbf8c0b2017-09-28 14:23:06 -070027#include "common/libs/auto_resources/auto_resources.h"
28#include "common/libs/fs/shared_select.h"
Greg Hartmana4ff2482017-10-03 16:35:00 -070029#include "common/libs/threads/cuttlefish_thread.h"
Tomasz Wiszkowskibbf8c0b2017-09-28 14:23:06 -070030#include "common/libs/threads/thunkers.h"
31#include "guest/commands/audio/vsoc_audio.h"
32#include "guest/commands/audio/vsoc_audio_input_stream.h"
33#include "guest/commands/audio/vsoc_audio_output_stream.h"
34#include "guest/libs/platform_support/api_level_fixes.h"
35#include "guest/libs/remoter/remoter_framework_pkt.h"
Tomasz Wiszkowskib34828c2017-09-28 14:03:41 -070036
37using avd::LockGuard;
38using avd::Mutex;
39
40namespace avd {
41
42namespace {
43template <typename F> struct HWDeviceThunker :
44 ThunkerBase<hw_device_t, GceAudio, F>{};
45template <typename F> struct AudioThunker :
46 ThunkerBase<audio_hw_device, GceAudio, F>{};
47template <typename F> struct AudioThreadThunker :
48 ThunkerBase<void, GceAudio, F>{};
49}
50
51GceAudio::~GceAudio() { }
52
53int GceAudio::Close() {
54 D("GceAudio::%s", __FUNCTION__);
55 {
56 LockGuard<Mutex> guard(lock_);
57 for (std::list<GceAudioOutputStream*>::iterator it = output_list_.begin();
58 it != output_list_.end(); ++it) {
59 delete *it;
60 }
61 for (input_map_t::iterator it = input_map_.begin();
62 it != input_map_.end(); ++it) {
63 delete it->second;
64 }
65 }
66 // Make certain that the listener thread wakes up
67 avd::SharedFD temp_client =
68 avd::SharedFD::SocketSeqPacketClient(
69 gce_audio_message::kAudioHALSocketName);
70 uint64_t dummy_val = 1;
71 terminate_listener_thread_event_->Write(&dummy_val, sizeof dummy_val);
72 pthread_join(listener_thread_, NULL);
73 delete this;
74 return 0;
75}
76
77avd::SharedFD GceAudio::GetAudioFd() {
78 LockGuard<Mutex> guard(lock_);
79 return audio_data_socket_;
80}
81
82size_t GceAudio::GetInputBufferSize(const audio_config*) const {
83 return IN_BUFFER_BYTES;
84}
85
86uint32_t GceAudio::GetSupportedDevices() const {
87 return AUDIO_DEVICE_OUT_EARPIECE |
88 AUDIO_DEVICE_OUT_SPEAKER |
89 AUDIO_DEVICE_OUT_DEFAULT |
90 AUDIO_DEVICE_IN_COMMUNICATION |
91 AUDIO_DEVICE_IN_BUILTIN_MIC |
92 AUDIO_DEVICE_IN_WIRED_HEADSET |
93 AUDIO_DEVICE_IN_VOICE_CALL |
94 AUDIO_DEVICE_IN_DEFAULT;
95}
96
97int GceAudio::InitCheck() const {
98 D("GceAudio::%s", __FUNCTION__);
99 return 0;
100}
101
102int GceAudio::SetMicMute(bool state) {
103 D("GceAudio::%s", __FUNCTION__);
104 LockGuard<Mutex> guard(lock_);
105 mic_muted_ = state;
106 return 0;
107}
108
109int GceAudio::GetMicMute(bool *state) const {
110 D("GceAudio::%s", __FUNCTION__);
111 LockGuard<Mutex> guard(lock_);
112 *state = mic_muted_;
113 return 0;
114}
115
116int GceAudio::OpenInputStream(audio_io_handle_t handle,
117 audio_devices_t devices,
118 audio_config *config,
119 audio_stream_in **stream_in,
120 audio_input_flags_t /*flags*/,
121 const char * /*address*/,
122 audio_source_t /*source*/) {
123 GceAudioInputStream* new_stream;
124 int rval = GceAudioInputStream::Open(
125 this, handle, devices, *config, &new_stream);
126 uint32_t stream_number;
127 if (new_stream) {
128 LockGuard<Mutex> guard(lock_);
129 stream_number = next_stream_number_++;
130 input_map_[stream_number] = new_stream;
131 }
132 // This should happen after the lock is released, hence the double check
133 if (new_stream) {
134 SendStreamUpdate(new_stream->GetStreamDescriptor(
135 stream_number, gce_audio_message::OPEN_INPUT_STREAM), MSG_DONTWAIT);
136 }
137 *stream_in = new_stream;
138 return rval;
139}
140
141
142void GceAudio::CloseInputStream(audio_stream_in *stream) {
143 GceAudioInputStream* astream = static_cast<GceAudioInputStream*>(stream);
144 gce_audio_message descriptor;
145 {
146 LockGuard<Mutex> guard(lock_);
147 // TODO(ghartman): This could be optimized if stream knew it's number.
148 for (input_map_t::iterator it = input_map_.begin();
149 it != input_map_.end(); ++it) {
150 if (it->second == stream) {
151 descriptor = it->second->GetStreamDescriptor(
152 it->first, gce_audio_message::CLOSE_INPUT_STREAM);
153 input_map_.erase(it);
154 break;
155 }
156 }
157 }
158 SendStreamUpdate(descriptor, MSG_DONTWAIT);
159 delete astream;
160}
161
162
163int GceAudio::OpenOutputStream(audio_io_handle_t handle,
164 audio_devices_t devices,
165 audio_output_flags_t flags,
166 audio_config *config,
167 audio_stream_out **stream_out,
168 const char * /*address*/) {
169 GceAudioOutputStream* new_stream;
170 int rval;
171 {
172 LockGuard<Mutex> guard(lock_);
173 rval = GceAudioOutputStream::Open(
174 this, handle, devices, flags, config, next_stream_number_++,
175 &new_stream);
176 if (new_stream) {
177 output_list_.push_back(new_stream);
178 }
179 }
180 if (new_stream) {
181 SendStreamUpdate(new_stream->GetStreamDescriptor(
182 gce_audio_message::OPEN_OUTPUT_STREAM), MSG_DONTWAIT);
183 }
184 *stream_out = new_stream;
185 return rval;
186}
187
188void GceAudio::CloseOutputStream(audio_stream_out *stream) {
189 GceAudioOutputStream* astream = static_cast<GceAudioOutputStream*>(stream);
190 gce_audio_message close;
191 {
192 LockGuard<Mutex> guard(lock_);
193 output_list_.remove(astream);
194 close = astream->GetStreamDescriptor(
195 gce_audio_message::CLOSE_OUTPUT_STREAM);
196 }
197 SendStreamUpdate(close, MSG_DONTWAIT);
198 delete astream;
199}
200
201int GceAudio::Dump(int fd) const {
202 LockGuard<Mutex> guard(lock_);
Tomasz Wiszkowskibbf8c0b2017-09-28 14:23:06 -0700203 VSOC_FDPRINTF(
Tomasz Wiszkowskib34828c2017-09-28 14:03:41 -0700204 fd,
205 "\nadev_dump:\n"
206 "\tmic_mute: %s\n"
207 "\tnum_outputs: %zu\n"
208 "\tnum_inputs: %zu\n\n",
209 mic_muted_ ? "true": "false",
210 output_list_.size(), input_map_.size());
211
212 for (std::list<GceAudioOutputStream*>::const_iterator it =
213 output_list_.begin();
214 it != output_list_.end(); ++it) {
215 (*it)->common.dump(&(*it)->common, fd);
216 }
217
218 for (input_map_t::const_iterator it = input_map_.begin();
219 it != input_map_.end(); ++it) {
220 (*it).second->common.dump(&(*it).second->common, fd);
221 }
222
223 return 0;
224}
225
226ssize_t GceAudio::SendMsg(const msghdr& msg, int flags) {
227 avd::SharedFD fd = GetAudioFd();
228 if (!fd->IsOpen()) {
229 return 0;
230 }
231 return fd->SendMsg(&msg, flags);
232}
233
234ssize_t GceAudio::SendStreamUpdate(
235 const gce_audio_message& stream_info, int flags) {
236 msghdr msg;
237 iovec msg_iov[1];
238 msg_iov[0].iov_base = const_cast<gce_audio_message*>(&stream_info);
239 msg_iov[0].iov_len = sizeof(gce_audio_message);
240 msg.msg_name = NULL;
241 msg.msg_namelen = 0;
242 msg.msg_iov = msg_iov;
243 msg.msg_iovlen = arraysize(msg_iov);
244 msg.msg_control = NULL;
245 msg.msg_controllen = 0;
246 msg.msg_flags = 0;
247 return SendMsg(msg, flags);
248}
249
250int GceAudio::SetVoiceVolume(float volume) {
251 D("GceAudio::%s: set voice volume %f", __FUNCTION__, volume);
252 voice_volume_ = volume;
253 return 0;
254}
255
256int GceAudio::SetMasterVolume(float volume) {
257 D("GceAudio::%s: set master volume %f", __FUNCTION__, volume);
258 master_volume_ = volume;
259 return 0;
260}
261
262int GceAudio::GetMasterVolume(float* volume) {
263 D("GceAudio::%s: get master volume %f", __FUNCTION__, master_volume_);
264 *volume = master_volume_;
265 return 0;
266}
267
268int GceAudio::SetMasterMute(bool muted) {
269 D("GceAudio::%s: set master muted %d", __FUNCTION__, muted);
270 master_muted_ = muted;
271 return 0;
272}
273
274int GceAudio::GetMasterMute(bool* muted) {
275 D("GceAudio::%s: get master muted %d", __FUNCTION__, master_muted_);
276 *muted = master_muted_;
277 return 0;
278}
279
280int GceAudio::SetMode(audio_mode_t mode) {
281 D("GceAudio::%s: new mode %d", __FUNCTION__, mode);
282 mode_ = mode;
283 return 0;
284}
285
286void* GceAudio::Listener() {
287 // TODO(ghartman): Consider tightening the mode on this later.
288 audio_listener_socket_ = avd::SharedFD::SocketSeqPacketServer(
289 gce_audio_message::kAudioHALSocketName, 0777);
290 if (!audio_listener_socket_->IsOpen()) {
291 ALOGE("GceAudio::%s: Could not listen for audio connections. (%s).",
292 __FUNCTION__, audio_listener_socket_->StrError());
293 return NULL;
294 }
295 ALOGI("GceAudio::%s: Listening for audio connections at %s",
296 __FUNCTION__, gce_audio_message::kAudioHALSocketName);
297 remoter_request_packet announce;
298 remoter_request_packet_init(&announce, kRemoterHALReady, 0);
299 announce.send_response = 0;
300 strncpy(announce.params.hal_ready_params.unix_socket,
301 gce_audio_message::kAudioHALSocketName,
302 sizeof(announce.params.hal_ready_params.unix_socket));
303 AutoCloseFileDescriptor remoter_socket(remoter_connect());
304 if (remoter_socket.IsError()) {
305 ALOGI("GceAudio::%s: Couldn't connect to remoter to register HAL (%s).",
306 __FUNCTION__, strerror(errno));
307 } else {
308 int err = remoter_do_single_request_with_socket(
309 remoter_socket, &announce, NULL);
310 if (err == -1) {
311 ALOGI("GceAudio::%s: HAL registration failed after connect (%s).",
312 __FUNCTION__, strerror(errno));
313 } else {
314 ALOGI("GceAudio::%s: HAL registered with the remoter", __FUNCTION__);
315 }
316 }
317 while (true) {
318 // Poll for new connections or the terminatation event.
319 // The listener is non-blocking. We send to at most one client. If a new
320 // client comes in disconnect the old one.
321 avd::SharedFDSet fd_set;
322 fd_set.Set(audio_listener_socket_);
323 fd_set.Set(terminate_listener_thread_event_);
324 if (avd::Select(&fd_set, NULL, NULL, NULL) <= 0) {
325 // There's no timeout, so 0 shouldn't happen.
326 ALOGE("GceAudio::%s: Error using shared Select", __FUNCTION__);
327 break;
328 }
329 if (fd_set.IsSet(terminate_listener_thread_event_)) {
330 break;
331 }
332 LOG_FATAL_IF(fd_set.IsSet(audio_listener_socket_),
333 "No error in Select() but nothing ready to read");
334 avd::SharedFD fd = avd::SharedFD::Accept(
335 *audio_listener_socket_);
336 if (!fd->IsOpen()) {
337 continue;
338 }
339 std::list<gce_audio_message> streams;
340 {
341 LockGuard<Mutex> guard(lock_);
342 // Do not do I/O while holding the lock. It could block the HAL
343 // implementation.
344 // Register the fd before dropping the lock to ensure that every
345 // active stream will appear when we first connect.
346 // Some output streams may appear twice if an open is active
347 // during the connect.
348 audio_data_socket_ = fd;
349 for (std::list<GceAudioOutputStream*>::iterator it = output_list_.begin();
350 it != output_list_.end(); ++it) {
351 streams.push_back((*it)->GetStreamDescriptor(
352 gce_audio_message::OPEN_OUTPUT_STREAM));
353 }
354 for (input_map_t::iterator it = input_map_.begin();
355 it != input_map_.end(); ++it) {
356 streams.push_back(it->second->GetStreamDescriptor(
357 it->first, gce_audio_message::OPEN_INPUT_STREAM));
358 }
359 }
360 for (std::list<gce_audio_message>::iterator it = streams.begin();
361 it != streams.end(); ++it) {
362 // We're willing to block because this is independent of the HAL
363 // implementation. We also don't want to forget to mention the input
364 // streams.
365 if (SendStreamUpdate(*it, 0) < 0) {
366 ALOGE("GceAudio::%s: Failed to announce open stream (%s)",
367 __FUNCTION__, fd->StrError());
368 }
369 }
370 }
371 return NULL;
372}
373
374int GceAudio::Open(const hw_module_t* module, const char* name,
375 hw_device_t** device) {
376 D("GceAudio::%s", __FUNCTION__);
377
378 if (strcmp(name, AUDIO_HARDWARE_INTERFACE)) {
379 ALOGE("GceAudio::%s: invalid module name %s (expected %s)",
380 __FUNCTION__, name, AUDIO_HARDWARE_INTERFACE);
381 return -EINVAL;
382 }
383
384 GceAudio* rval = new GceAudio;
385 int err = pthread_create(
386 &rval->listener_thread_, NULL,
387 AudioThreadThunker<void*()>::call<&GceAudio::Listener>, rval);
388 if (err) {
389 ALOGE("GceAudio::%s: Unable to start listener thread (%s)", __FUNCTION__,
390 strerror(err));
391 }
392 rval->common.tag = HARDWARE_DEVICE_TAG;
393 rval->common.version = version_;
394 rval->common.module = const_cast<hw_module_t *>(module);
395 rval->common.close = HWDeviceThunker<int()>::call<&GceAudio::Close>;
396
397#if !defined(AUDIO_DEVICE_API_VERSION_2_0)
398 // This HAL entry is supported only on AUDIO_DEVICE_API_VERSION_1_0.
399 // In fact, with version 2.0 the device numbers were orgainized in a
400 // way that makes the return value nonsense.
401 // Skipping the assignment is ok: the memset in the constructor already
402 // put a NULL here.
403 rval->get_supported_devices =
404 AudioThunker<uint32_t()>::call<&GceAudio::GetSupportedDevices>;
405#endif
406 rval->init_check = AudioThunker<int()>::call<&GceAudio::InitCheck>;
407
408 rval->set_voice_volume =
409 AudioThunker<int(float)>::call<&GceAudio::SetVoiceVolume>;
410 rval->set_master_volume =
411 AudioThunker<int(float)>::call<&GceAudio::SetMasterVolume>;
412 rval->get_master_volume =
413 AudioThunker<int(float*)>::call<&GceAudio::GetMasterVolume>;
414
415#if defined(AUDIO_DEVICE_API_VERSION_2_0)
416 rval->set_master_mute =
417 AudioThunker<int(bool)>::call<&GceAudio::SetMasterMute>;
418 rval->get_master_mute =
419 AudioThunker<int(bool*)>::call<&GceAudio::GetMasterMute>;
420#endif
421
422 rval->set_mode = AudioThunker<int(audio_mode_t)>::call<&GceAudio::SetMode>;
423 rval->set_mic_mute = AudioThunker<int(bool)>::call<&GceAudio::SetMicMute>;
424 rval->get_mic_mute =
425 AudioThunker<int(bool*)>::call<&GceAudio::GetMicMute>;
426
427 rval->set_parameters =
428 AudioThunker<int(const char*)>::call<&GceAudio::SetParameters>;
429 rval->get_parameters =
430 AudioThunker<char*(const char*)>::call<&GceAudio::GetParameters>;
431
432 rval->get_input_buffer_size =
433 AudioThunker<size_t(const audio_config*)>::call<
434 &GceAudio::GetInputBufferSize>;
435
436 rval->open_input_stream =
437 AudioThunker<GceAudio::OpenInputStreamHAL_t>::call<
438 &GceAudio::OpenInputStreamCurrentHAL>;
439 rval->close_input_stream =
440 AudioThunker<void(audio_stream_in*)>::call<&GceAudio::CloseInputStream>;
441
442 rval->open_output_stream =
443 AudioThunker<GceAudio::OpenOutputStreamHAL_t>::call<
444 &GceAudio::OpenOutputStreamCurrentHAL>;
445 rval->close_output_stream =
446 AudioThunker<void(audio_stream_out*)>::call<&GceAudio::CloseOutputStream>;
447
448 rval->dump = AudioThunker<int(int)>::call<&GceAudio::Dump>;
449
450 *device = &rval->common;
451 return 0;
452}
453
454int GceAudio::SetParameters(const char *kvpairs) {
455 ALOGE("GceAudio::%s: not implemented", __FUNCTION__);
456 if (kvpairs) D("GceAudio::%s: kvpairs %s", __FUNCTION__, kvpairs);
457 return 0;
458}
459
460
461char* GceAudio::GetParameters(const char *keys) const {
462 ALOGE("GceAudio::%s: not implemented", __FUNCTION__);
463 if (keys) D("GceAudio::%s: kvpairs %s", __FUNCTION__, keys);
464 return strdup("");
465}
466
467int GceAudio::SetStreamParameters(
468 struct audio_stream *stream, const char *kv_pairs) {
469 struct str_parms *parms = str_parms_create_str(kv_pairs);
470 if (!parms) {
471 return 0;
472 }
473 int sample_rate;
474 if (str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_SAMPLING_RATE,
475 &sample_rate) >= 0) {
476 stream->set_sample_rate(stream, sample_rate);
477 }
478 int format;
479 if (str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_FORMAT,
480 &format) >= 0) {
481 stream->set_format(stream, static_cast<audio_format_t>(format));
482 }
483 int routing;
484 if (str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_ROUTING,
485 &routing) >= 0) {
486 stream->set_device(stream, static_cast<audio_devices_t>(routing));
487 }
488 if (str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE,
489 &routing) >= 0) {
490 stream->set_device(stream, static_cast<audio_devices_t>(routing));
491 }
492 str_parms_destroy(parms);
493 return 0;
494}
495
496}