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