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 17 #include <pthread.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <cstdint> 21 22 extern "C"{ 23 #include <cutils/str_parms.h> 24 } 25 26 #include "common/libs/auto_resources/auto_resources.h" 27 #include "common/libs/threads/thunkers.h" 28 #include "guest/hals/audio/audio_hal.h" 29 #include "guest/hals/audio/vsoc_audio.h" 30 #include "guest/hals/audio/vsoc_audio_input_stream.h" 31 #include "guest/libs/platform_support/api_level_fixes.h" 32 33 namespace cvd { 34 35 namespace { 36 template <typename F> struct Thunker : 37 ThunkerBase<audio_stream, GceAudioInputStream, F>{}; 38 template <typename F> struct InThunker : 39 ThunkerBase<audio_stream_in, GceAudioInputStream, F>{}; 40 } 41 42 #if defined(AUDIO_DEVICE_API_VERSION_3_0) 43 static inline size_t GceAudioFrameSize(const audio_stream_in* s) { 44 return audio_stream_in_frame_size(s); 45 } 46 #elif defined(AUDIO_DEVICE_API_VERSION_2_0) 47 static inline size_t GceAudioFrameSize(const audio_stream_in* s) { 48 49 return audio_stream_frame_size(&s->common); 50 } 51 #else 52 static inline size_t GceAudioFrameSize(audio_stream_in* s) { 53 54 return audio_stream_frame_size(&s->common); 55 } 56 #endif 57 58 GceAudioInputStream::GceAudioInputStream( 59 cvd::GceAudio* dev, audio_devices_t devices, const audio_config& config) 60 : audio_stream_in(), 61 dev_(dev), 62 config_(config), 63 gain_(0.0), 64 device_(devices) { 65 common.get_sample_rate = 66 Thunker<uint32_t()>::call<&GceAudioInputStream::GetSampleRate>; 67 common.set_sample_rate = 68 Thunker<int(uint32_t)>::call<&GceAudioInputStream::SetSampleRate>; 69 common.get_buffer_size = 70 Thunker<size_t()>::call<&GceAudioInputStream::GetBufferSize>; 71 common.get_channels = 72 Thunker<audio_channel_mask_t()>::call<&GceAudioInputStream::GetChannels>; 73 common.get_device = 74 Thunker<audio_devices_t()>::call<&GceAudioInputStream::GetDevice>; 75 common.set_device = 76 Thunker<int(audio_devices_t)>::call<&GceAudioInputStream::SetDevice>; 77 common.get_format = 78 Thunker<audio_format_t()>::call<&GceAudioInputStream::GetFormat>; 79 common.set_format = 80 Thunker<int(audio_format_t)>::call<&GceAudioInputStream::SetFormat>; 81 common.standby = 82 Thunker<int()>::call<&GceAudioInputStream::Standby>; 83 common.dump = 84 Thunker<int(int)>::call<&GceAudioInputStream::Dump>; 85 common.set_parameters = GceAudio::SetStreamParameters; 86 common.get_parameters = 87 Thunker<char*(const char *)>::call<&GceAudioInputStream::GetParameters>; 88 common.add_audio_effect = 89 Thunker<int(effect_handle_t)>::call<&GceAudioInputStream::AddAudioEffect>; 90 common.remove_audio_effect = Thunker<int(effect_handle_t)>::call< 91 &GceAudioInputStream::RemoveAudioEffect>; 92 set_gain = InThunker<int(float)>::call<&GceAudioInputStream::SetGain>; 93 read = InThunker<ssize_t(void*, size_t)>::call< 94 &GceAudioInputStream::Read>; 95 get_input_frames_lost = InThunker<uint32_t()>::call< 96 &GceAudioInputStream::GetInputFramesLost>; 97 frame_size_ = GceAudioFrameSize(this); 98 buffer_model_.reset( 99 new SimulatedInputBuffer(config_.sample_rate, GetBufferSize() / 100 frame_size_)); 101 reported_lost_frames_ = 0; 102 } 103 104 gce_audio_message GceAudioInputStream::GetStreamDescriptor( 105 uint32_t stream_number, gce_audio_message::message_t event) { 106 gce_audio_message rval; 107 rval.message_type = event; 108 rval.stream_number = stream_number; 109 rval.frame_num = buffer_model_->GetCurrentItemNum(); 110 rval.time_presented = 111 buffer_model_->GetLastUpdatedTime().SinceEpoch().GetTS(); 112 rval.frame_rate = config_.sample_rate; 113 rval.channel_mask = config_.channel_mask; 114 rval.format = config_.format; 115 rval.frame_size = frame_size_; 116 return rval; 117 } 118 119 int GceAudioInputStream::Open(GceAudio* dev, 120 audio_io_handle_t /*handle*/, 121 audio_devices_t devices, 122 const audio_config& config, 123 GceAudioInputStream** stream_in) { 124 D("GceAudioInputStream::%s", __FUNCTION__); 125 *stream_in = new GceAudioInputStream(dev, devices, config); 126 return 0; 127 } 128 129 int GceAudioInputStream::SetFormat(audio_format_t format) { 130 config_.format = format; 131 frame_size_ = GceAudioFrameSize(this); 132 return 0; 133 } 134 135 int GceAudioInputStream::Dump(int fd) const { 136 D("GceAudioInputStream::%s", __FUNCTION__); 137 VSOC_FDPRINTF( 138 fd, 139 "\tInputSteam Dump:\n" 140 "\t\tsample rate: %u\n" 141 "\t\tbuffer size: %zu\n" 142 "\t\tchannel mask: %08x\n" 143 "\t\tformat: %d\n" 144 "\t\tdevice: %08x\n" 145 "\t\taudio dev: %p\n\n", 146 GetSampleRate(), GetBufferSize(), 147 GetChannels(), GetFormat(), device_, dev_); 148 return 0; 149 } 150 151 int GceAudioInputStream::SetSampleRate(uint32_t sample_rate) { 152 if (sample_rate != config_.sample_rate) { 153 config_.sample_rate = sample_rate; 154 buffer_model_.reset( 155 new SimulatedInputBuffer(sample_rate, GetBufferSize() / frame_size_)); 156 reported_lost_frames_ = 0; 157 } 158 return 0; 159 } 160 161 char* GceAudioInputStream::GetParameters(const char* keys) const { 162 D("GceAudioInputStream::%s", __FUNCTION__); 163 if (keys) D("GceAudioInputStream::%s keys %s", __FUNCTION__, keys); 164 165 str_parms* query = str_parms_create_str(keys); 166 str_parms* reply = str_parms_create(); 167 168 char value[256]; 169 int ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_ROUTING, 170 value, sizeof(value)); 171 char* str; 172 if (ret >= 0) { 173 str_parms_add_int(reply, AUDIO_PARAMETER_STREAM_ROUTING, device_); 174 str = strdup(str_parms_to_str(reply)); 175 } else { 176 str = strdup(keys); 177 } 178 str_parms_destroy(query); 179 str_parms_destroy(reply); 180 return str; 181 } 182 183 184 ssize_t GceAudioInputStream::Read(void* buffer, size_t bytes) { 185 int64_t available = buffer_model_->RemoveFromInputBuffer( 186 bytes / frame_size_, false) * frame_size_; 187 ssize_t rval = available; 188 if ((rval != available) || (rval < 0)) { 189 ALOGE("GceAudioInputStream:%s got bad value from " 190 "RemoveFromInputBuffer %" PRId64, __FUNCTION__, available); 191 return -1; 192 } 193 memset(buffer, 0, rval); 194 return rval; 195 } 196 197 } 198