blob: 040e1e717514c524dafa5448421de4ca93dc3b97 [file] [log] [blame]
Cody Schuffelen134ff032019-11-22 00:25:32 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
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 */
16#include "guest/hals/audio/legacy/audio_hal.h"
17
18#include <inttypes.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <sys/time.h>
22#include <fcntl.h>
23
24extern "C" {
25#include <cutils/str_parms.h>
26}
27
28#include "common/libs/auto_resources/auto_resources.h"
29#include "common/libs/fs/shared_select.h"
30#include "common/libs/threads/cuttlefish_thread.h"
31#include "common/libs/threads/thunkers.h"
32#include "common/vsoc/lib/circqueue_impl.h"
33#include "guest/hals/audio/legacy/vsoc_audio.h"
34#include "guest/hals/audio/legacy/vsoc_audio_input_stream.h"
35#include "guest/hals/audio/legacy/vsoc_audio_output_stream.h"
36#include "guest/libs/remoter/remoter_framework_pkt.h"
37
38using cvd::LockGuard;
39using cvd::Mutex;
40
41namespace cvd {
42
43GceAudio::~GceAudio() { }
44
45int GceAudio::Close() {
46 D("GceAudio::%s", __FUNCTION__);
47 {
48 LockGuard<Mutex> guard(lock_);
49 for (std::list<GceAudioOutputStream*>::iterator it = output_list_.begin();
50 it != output_list_.end(); ++it) {
51 delete *it;
52 }
53 for (input_map_t::iterator it = input_map_.begin();
54 it != input_map_.end(); ++it) {
55 delete it->second;
56 }
57 }
58 delete this;
59 return 0;
60}
61
62size_t GceAudio::GetInputBufferSize(const audio_config*) const {
63 return IN_BUFFER_BYTES;
64}
65
66uint32_t GceAudio::GetSupportedDevices() const {
67 return AUDIO_DEVICE_OUT_EARPIECE |
68 AUDIO_DEVICE_OUT_SPEAKER |
69 AUDIO_DEVICE_OUT_DEFAULT |
70 AUDIO_DEVICE_IN_COMMUNICATION |
71 AUDIO_DEVICE_IN_BUILTIN_MIC |
72 AUDIO_DEVICE_IN_WIRED_HEADSET |
73 AUDIO_DEVICE_IN_VOICE_CALL |
74 AUDIO_DEVICE_IN_DEFAULT;
75}
76
77int GceAudio::InitCheck() const {
78 D("GceAudio::%s", __FUNCTION__);
79 return 0;
80}
81
82int GceAudio::SetMicMute(bool state) {
83 D("GceAudio::%s", __FUNCTION__);
84 LockGuard<Mutex> guard(lock_);
85 mic_muted_ = state;
86 return 0;
87}
88
89int GceAudio::GetMicMute(bool *state) const {
90 D("GceAudio::%s", __FUNCTION__);
91 LockGuard<Mutex> guard(lock_);
92 *state = mic_muted_;
93 return 0;
94}
95
96int GceAudio::OpenInputStream(audio_io_handle_t handle,
97 audio_devices_t devices,
98 audio_config *config,
99 audio_stream_in **stream_in,
100 audio_input_flags_t /*flags*/,
101 const char * /*address*/,
102 audio_source_t /*source*/) {
103 GceAudioInputStream* new_stream;
104 int rval = GceAudioInputStream::Open(
105 this, handle, devices, *config, &new_stream);
106 uint32_t stream_number;
107 if (new_stream) {
108 LockGuard<Mutex> guard(lock_);
109 stream_number = next_stream_number_++;
110 input_map_[stream_number] = new_stream;
111 }
112 // This should happen after the lock is released, hence the double check
113 if (new_stream) {
114 SendStreamUpdate(new_stream->GetStreamDescriptor(
115 stream_number, gce_audio_message::OPEN_INPUT_STREAM), MSG_DONTWAIT);
116 }
117 *stream_in = new_stream;
118 return rval;
119}
120
121
122void GceAudio::CloseInputStream(audio_stream_in *stream) {
123 GceAudioInputStream* astream = static_cast<GceAudioInputStream*>(stream);
124 gce_audio_message descriptor;
125 {
126 LockGuard<Mutex> guard(lock_);
127 // TODO(ghartman): This could be optimized if stream knew it's number.
128 for (input_map_t::iterator it = input_map_.begin();
129 it != input_map_.end(); ++it) {
130 if (it->second == stream) {
131 descriptor = it->second->GetStreamDescriptor(
132 it->first, gce_audio_message::CLOSE_INPUT_STREAM);
133 input_map_.erase(it);
134 break;
135 }
136 }
137 }
138 SendStreamUpdate(descriptor, MSG_DONTWAIT);
139 delete astream;
140}
141
142
143int GceAudio::OpenOutputStream(audio_io_handle_t handle,
144 audio_devices_t devices,
145 audio_output_flags_t flags,
146 audio_config *config,
147 audio_stream_out **stream_out,
148 const char * /*address*/) {
149 GceAudioOutputStream* new_stream;
150 int rval;
151 {
152 LockGuard<Mutex> guard(lock_);
153 rval = GceAudioOutputStream::Open(
154 this, handle, devices, flags, config, next_stream_number_++,
155 &new_stream);
156 if (new_stream) {
157 output_list_.push_back(new_stream);
158 }
159 }
160 if (new_stream) {
161 SendStreamUpdate(new_stream->GetStreamDescriptor(
162 gce_audio_message::OPEN_OUTPUT_STREAM), MSG_DONTWAIT);
163 }
164 *stream_out = new_stream;
165 return rval;
166}
167
168void GceAudio::CloseOutputStream(audio_stream_out *stream) {
169 GceAudioOutputStream* astream = static_cast<GceAudioOutputStream*>(stream);
170 gce_audio_message close;
171 {
172 LockGuard<Mutex> guard(lock_);
173 output_list_.remove(astream);
174 close = astream->GetStreamDescriptor(
175 gce_audio_message::CLOSE_OUTPUT_STREAM);
176 }
177 SendStreamUpdate(close, MSG_DONTWAIT);
178 delete astream;
179}
180
181int GceAudio::Dump(int fd) const {
182 LockGuard<Mutex> guard(lock_);
183 dprintf(
184 fd,
185 "\nadev_dump:\n"
186 "\tmic_mute: %s\n"
187 "\tnum_outputs: %zu\n"
188 "\tnum_inputs: %zu\n\n",
189 mic_muted_ ? "true": "false",
190 output_list_.size(), input_map_.size());
191
192 for (std::list<GceAudioOutputStream*>::const_iterator it =
193 output_list_.begin();
194 it != output_list_.end(); ++it) {
195 (*it)->common.dump(&(*it)->common, fd);
196 }
197
198 for (input_map_t::const_iterator it = input_map_.begin();
199 it != input_map_.end(); ++it) {
200 (*it).second->common.dump(&(*it).second->common, fd);
201 }
202
203 return 0;
204}
205
206ssize_t GceAudio::SendMsg(const msghdr& msg, int /* flags */) {
207 intptr_t res = audio_data_rv_->data()->audio_queue.Writev(
208 audio_data_rv_,
209 msg.msg_iov,
210 msg.msg_iovlen,
211 true /* non_blocking */);
212
213 if (res < 0) {
214 ALOGV("GceAudio::%s: CircularPacketQueue::Write returned %" PRIiPTR,
215 __FUNCTION__,
216 res);
217 }
218
219 return static_cast<ssize_t>(res);
220}
221
222ssize_t GceAudio::SendStreamUpdate(
223 const gce_audio_message& stream_info, int flags) {
224 msghdr msg;
225 iovec msg_iov[1];
226 msg_iov[0].iov_base = const_cast<gce_audio_message*>(&stream_info);
227 msg_iov[0].iov_len = sizeof(gce_audio_message);
228 msg.msg_name = NULL;
229 msg.msg_namelen = 0;
230 msg.msg_iov = msg_iov;
231 msg.msg_iovlen = arraysize(msg_iov);
232 msg.msg_control = NULL;
233 msg.msg_controllen = 0;
234 msg.msg_flags = 0;
235 return SendMsg(msg, flags);
236}
237
238int GceAudio::SetVoiceVolume(float volume) {
239 D("GceAudio::%s: set voice volume %f", __FUNCTION__, volume);
240 voice_volume_ = volume;
241 return 0;
242}
243
244int GceAudio::SetMasterVolume(float volume) {
245 D("GceAudio::%s: set master volume %f", __FUNCTION__, volume);
246 master_volume_ = volume;
247 return 0;
248}
249
250int GceAudio::GetMasterVolume(float* volume) {
251 D("GceAudio::%s: get master volume %f", __FUNCTION__, master_volume_);
252 *volume = master_volume_;
253 return 0;
254}
255
256int GceAudio::SetMasterMute(bool muted) {
257 D("GceAudio::%s: set master muted %d", __FUNCTION__, muted);
258 master_muted_ = muted;
259 return 0;
260}
261
262int GceAudio::GetMasterMute(bool* muted) {
263 D("GceAudio::%s: get master muted %d", __FUNCTION__, master_muted_);
264 *muted = master_muted_;
265 return 0;
266}
267
268int GceAudio::SetMode(audio_mode_t mode) {
269 D("GceAudio::%s: new mode %d", __FUNCTION__, mode);
270 mode_ = mode;
271 return 0;
272}
273
274int GceAudio::Open(const hw_module_t* module, const char* name,
275 hw_device_t** device) {
276 D("GceAudio::%s", __FUNCTION__);
277
278 if (strcmp(name, AUDIO_HARDWARE_INTERFACE)) {
279 ALOGE("GceAudio::%s: invalid module name %s (expected %s)",
280 __FUNCTION__, name, AUDIO_HARDWARE_INTERFACE);
281 return -EINVAL;
282 }
283
284 GceAudio* rval = new GceAudio;
285
286 rval->audio_data_rv_ = AudioDataRegionView::GetInstance();
287 rval->audio_worker_ = rval->audio_data_rv_->StartWorker();
288
289 rval->common.tag = HARDWARE_DEVICE_TAG;
290 rval->common.version = version_;
291 rval->common.module = const_cast<hw_module_t *>(module);
292 rval->common.close = cvd::thunk<hw_device_t, &GceAudio::Close>;
293
294#if !defined(AUDIO_DEVICE_API_VERSION_2_0)
295 // This HAL entry is supported only on AUDIO_DEVICE_API_VERSION_1_0.
296 // In fact, with version 2.0 the device numbers were orgainized in a
297 // way that makes the return value nonsense.
298 // Skipping the assignment is ok: the memset in the constructor already
299 // put a NULL here.
300 rval->get_supported_devices =
301 cvd::thunk<audio_hw_device, &GceAudio::GetSupportedDevices>;
302#endif
303 rval->init_check = cvd::thunk<audio_hw_device, &GceAudio::InitCheck>;
304
305 rval->set_voice_volume =
306 cvd::thunk<audio_hw_device, &GceAudio::SetVoiceVolume>;
307 rval->set_master_volume =
308 cvd::thunk<audio_hw_device, &GceAudio::SetMasterVolume>;
309 rval->get_master_volume =
310 cvd::thunk<audio_hw_device, &GceAudio::GetMasterVolume>;
311
312#if defined(AUDIO_DEVICE_API_VERSION_2_0)
313 rval->set_master_mute =
314 cvd::thunk<audio_hw_device, &GceAudio::SetMasterMute>;
315 rval->get_master_mute =
316 cvd::thunk<audio_hw_device, &GceAudio::GetMasterMute>;
317#endif
318
319 rval->set_mode = cvd::thunk<audio_hw_device, &GceAudio::SetMode>;
320 rval->set_mic_mute = cvd::thunk<audio_hw_device, &GceAudio::SetMicMute>;
321 rval->get_mic_mute = cvd::thunk<audio_hw_device, &GceAudio::GetMicMute>;
322
323 rval->set_parameters = cvd::thunk<audio_hw_device, &GceAudio::SetParameters>;
324 rval->get_parameters = cvd::thunk<audio_hw_device, &GceAudio::GetParameters>;
325
326 rval->get_input_buffer_size =
327 cvd::thunk<audio_hw_device, &GceAudio::GetInputBufferSize>;
328
329 rval->open_input_stream =
330 cvd::thunk<audio_hw_device, &GceAudio::OpenInputStreamCurrentHAL>;
331 rval->close_input_stream =
332 cvd::thunk<audio_hw_device, &GceAudio::CloseInputStream>;
333
334 rval->open_output_stream =
335 cvd::thunk<audio_hw_device, &GceAudio::OpenOutputStreamCurrentHAL>;
336 rval->close_output_stream =
337 cvd::thunk<audio_hw_device, &GceAudio::CloseOutputStream>;
338
339 rval->dump = cvd::thunk<audio_hw_device, &GceAudio::Dump>;
340
341 *device = &rval->common;
342 return 0;
343}
344
345int GceAudio::SetParameters(const char *kvpairs) {
346 ALOGE("GceAudio::%s: not implemented", __FUNCTION__);
347 if (kvpairs) D("GceAudio::%s: kvpairs %s", __FUNCTION__, kvpairs);
348 return 0;
349}
350
351
352char* GceAudio::GetParameters(const char *keys) const {
353 ALOGE("GceAudio::%s: not implemented", __FUNCTION__);
354 if (keys) D("GceAudio::%s: kvpairs %s", __FUNCTION__, keys);
355 return strdup("");
356}
357
358int GceAudio::SetStreamParameters(
359 struct audio_stream *stream, const char *kv_pairs) {
360 struct str_parms *parms = str_parms_create_str(kv_pairs);
361 if (!parms) {
362 return 0;
363 }
364 int sample_rate;
365 if (str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_SAMPLING_RATE,
366 &sample_rate) >= 0) {
367 stream->set_sample_rate(stream, sample_rate);
368 }
369 int format;
370 if (str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_FORMAT,
371 &format) >= 0) {
372 stream->set_format(stream, static_cast<audio_format_t>(format));
373 }
374 int routing;
375 if (str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_ROUTING,
376 &routing) >= 0) {
377 stream->set_device(stream, static_cast<audio_devices_t>(routing));
378 }
379 if (str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE,
380 &routing) >= 0) {
381 stream->set_device(stream, static_cast<audio_devices_t>(routing));
382 }
383 str_parms_destroy(parms);
384 return 0;
385}
386
387}