Home | History | Annotate | Download | only in audio
      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