• Home
  • 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/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