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