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