Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 1 | /* |
Tomasz Wiszkowski | bbf8c0b | 2017-09-28 14:23:06 -0700 | [diff] [blame] | 2 | * Copyright (C) 2017 The Android Open Source Project |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 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 | */ |
Tomasz Wiszkowski | bbf8c0b | 2017-09-28 14:23:06 -0700 | [diff] [blame] | 16 | #pragma once |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 17 | |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 18 | #include <list> |
| 19 | #include <map> |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 20 | |
Tomasz Wiszkowski | bbf8c0b | 2017-09-28 14:23:06 -0700 | [diff] [blame] | 21 | #include "common/libs/fs/shared_fd.h" |
Greg Hartman | a4ff248 | 2017-10-03 16:35:00 -0700 | [diff] [blame] | 22 | #include "common/libs/threads/cuttlefish_thread.h" |
Andreas Huber | cc1cd95 | 2018-01-18 12:57:33 -0800 | [diff] [blame^] | 23 | #include "common/vsoc/lib/audio_data_region_view.h" |
Greg Hartman | 0f4c835 | 2017-12-20 13:33:46 -0800 | [diff] [blame] | 24 | #include "guest/hals/audio/audio_hal.h" |
| 25 | #include "guest/hals/audio/vsoc_audio_input_stream.h" |
| 26 | #include "guest/hals/audio/vsoc_audio_message.h" |
Tomasz Wiszkowski | bbf8c0b | 2017-09-28 14:23:06 -0700 | [diff] [blame] | 27 | #include "guest/libs/platform_support/api_level_fixes.h" |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 28 | |
Greg Hartman | 153b106 | 2017-11-11 12:09:21 -0800 | [diff] [blame] | 29 | namespace cvd { |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 30 | |
| 31 | class GceAudioInputStream; |
| 32 | class GceAudioOutputStream; |
| 33 | |
| 34 | class GceAudio : public audio_hw_device { |
| 35 | public: |
| 36 | // This common code manipulates the parameters of input and output streams. |
| 37 | static int SetStreamParameters(struct audio_stream *, const char *); |
| 38 | |
| 39 | ~GceAudio(); |
| 40 | |
| 41 | // Non-HAL methods that are part of the GCE implementation. |
| 42 | // Most of these are used by the input and output streams. |
| 43 | |
| 44 | // Returns true if the microphone is muted. Used by input streams. |
| 45 | bool IsMicrophoneMuted() { |
Greg Hartman | 153b106 | 2017-11-11 12:09:21 -0800 | [diff] [blame] | 46 | cvd::LockGuard<cvd::Mutex> guard(lock_); |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 47 | return mic_muted_; |
| 48 | } |
| 49 | |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 50 | // Send a message to the connected streamer. |
| 51 | // Returns: |
| 52 | // 0 if there is no streamer. |
| 53 | // >0 if the message was sent. |
| 54 | // -1 if there was an error. |
| 55 | ssize_t SendMsg(const msghdr&, int flags); |
| 56 | |
| 57 | // Sends a stream update to the connected streamer. |
| 58 | // Stream updates have no frames. Use SendMsg if the message has frames. |
| 59 | // 0 if there is no streamer. |
| 60 | // >0 if the message was sent. |
| 61 | // -1 if there was an error. |
| 62 | ssize_t SendStreamUpdate( |
| 63 | const gce_audio_message& stream_info, int flags); |
| 64 | |
| 65 | // Callbacks for the Android audio_module HAL interface. |
| 66 | // Most of the comments below are copied from |
| 67 | // libhardware/include/hardware/audio.h |
| 68 | // |
| 69 | // Where the is a conflict the comments there apply. |
| 70 | // By default these methods return 0 on success -<errno> for failure. |
| 71 | |
| 72 | // Opens the device. |
| 73 | static int Open(const hw_module_t* module, const char* name, |
| 74 | hw_device_t** device); |
| 75 | |
| 76 | // Closes the device, closing any open input streams and output streams. |
| 77 | int Close(); |
| 78 | |
| 79 | // Closes the input stream, throwing away any data in the buffer. |
| 80 | void CloseInputStream(audio_stream_in* stream); |
| 81 | |
| 82 | // Closes the output stream without waiting for the buffer to clear. |
| 83 | void CloseOutputStream(audio_stream_out* stream); |
| 84 | |
| 85 | // Creates an audio patch between several source and sink ports. |
| 86 | // The handle is allocated by the HAL and should be unique for this |
| 87 | // audio HAL module. |
| 88 | // TODO(ghartman): Implement this as part of HAL 3.0 |
| 89 | //int CreateAudioPatch(unsigned int num_sources, |
| 90 | // const struct audio_port_config *sources, |
| 91 | // unsigned int num_sinks, |
| 92 | // const struct audio_port_config *sinks, |
| 93 | // audio_patch_handle_t *handle); |
| 94 | |
| 95 | // dumps the state of the audio hardware to the given fd. |
| 96 | // This information can be retrieved using the dumpsys utility. |
| 97 | int Dump(int fd) const; |
| 98 | |
| 99 | // Fills the list of supported attributes for a given audio port. |
| 100 | // As input, "port" contains the information (type, role, address etc...) |
| 101 | // needed by the HAL to identify the port. |
| 102 | // As output, "port" contains possible attributes (sampling rates, formats, |
| 103 | // channel masks, gain controllers...) for this port. |
| 104 | // TODO(ghartman): Implement this as part of HAL 3.0 |
| 105 | // int GetAudioPort(struct audio_port *port); |
| 106 | |
| 107 | // Sets audio port configuration |
| 108 | // TODO(ghartman): Implement this as part of HAL 3.0 |
| 109 | // int SetAudioPortConfig(const struct audio_port_config *config); |
| 110 | |
| 111 | size_t GetInputBufferSize(const audio_config*) const; |
| 112 | |
| 113 | // Gets the current master volume value for the HAL, if the HAL supports |
| 114 | // master volume control. AudioFlinger will query this value from the |
| 115 | // primary audio HAL when the service starts and use the value for setting |
| 116 | // the initial master volume across all HALs. HALs which do not support |
| 117 | // this method may leave it set to NULL. |
| 118 | int GetMasterVolume(float* /*volume*/); |
| 119 | |
| 120 | // Get the current master mute status for the HAL, if the HAL supports |
| 121 | // master mute control. AudioFlinger will query this value from the primary |
| 122 | // audio HAL when the service starts and use the value for setting the |
| 123 | // initial master mute across all HALs. HALs which do not support this |
| 124 | // method may leave it set to NULL. |
| 125 | int GetMasterMute(bool* muted); |
| 126 | |
| 127 | // Gets the audio mute status for the microphone. |
| 128 | int GetMicMute(bool* state) const; |
| 129 | |
| 130 | // Retrieves the global audio parameters. |
| 131 | // TODO(ghartman): Implement this. |
| 132 | char* GetParameters(const char* keys) const; |
| 133 | |
| 134 | // Enumerates what devices are supported by each audio_hw_device |
| 135 | // implementation. |
| 136 | // Return value is a bitmask of 1 or more values of audio_devices_t |
| 137 | // used by audio flinger. |
| 138 | // NOTE: audio HAL implementations starting with |
| 139 | // AUDIO_DEVICE_API_VERSION_2_0 do not implement this function. |
| 140 | // AUDIO_DEVICE_API_VERSION_2_0 was the current version as of JB-MR1 |
| 141 | // All supported devices should be listed in audio_policy.conf |
| 142 | // file and the audio policy manager must choose the appropriate |
| 143 | // audio module based on information in this file. |
| 144 | uint32_t GetSupportedDevices() const; |
| 145 | |
| 146 | // Checks to see if the audio hardware interface has been initialized. |
| 147 | // Always returns 0 to indicate success, but -ENODEV is also allowed to |
| 148 | // indicate failure. |
| 149 | int InitCheck() const; |
| 150 | |
| 151 | // Creates an additional hardware input stream. |
| 152 | // Additional parameters were added in the 3.0 version of the HAL. |
| 153 | // These defaults make it easier to implement a cross-branch device. |
| 154 | int OpenInputStream( |
| 155 | audio_io_handle_t handle, |
| 156 | audio_devices_t devices, audio_config *config, |
| 157 | audio_stream_in **stream_in, |
| 158 | audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE, |
| 159 | const char* address = 0, |
| 160 | audio_source_t source = AUDIO_SOURCE_DEFAULT); |
| 161 | |
| 162 | // Creates an additional output stream. |
| 163 | // The "address" parameter qualifies the "devices" audio device type if |
| 164 | // needed. On GCE we ignore it for now because we simulate a single SoC |
| 165 | // hw devices. |
| 166 | // |
| 167 | // The format format depends on the device type: |
| 168 | // Bluetooth devices use the MAC address of the device in the form |
| 169 | // "00:11:22:AA:BB:CC" |
| 170 | // USB devices use the ALSA card and device numbers in the form |
| 171 | // "card=X;device=Y" |
| 172 | // Other devices may use a number or any other string. |
| 173 | int OpenOutputStream( |
| 174 | audio_io_handle_t handle, |
| 175 | audio_devices_t devices, audio_output_flags_t flags, |
| 176 | audio_config* config, audio_stream_out** stream_out, |
| 177 | const char* address = 0); |
| 178 | |
| 179 | // Releases an audio patch. |
| 180 | // TODO(ghartman): Implement this as part of HAL 3.0 |
| 181 | //int ReleaseAudioPatch(audio_patch_handle_t handle); |
| 182 | |
| 183 | // Sets the audio mute status for all audio activities. If any value other |
| 184 | // than 0 is returned, the software mixer will emulate this capability. |
| 185 | // The GCE implementation always returns 0. |
| 186 | int SetMasterMute(bool muted); |
| 187 | |
| 188 | // Sets the audio volume for all audio activities other than voice call. |
| 189 | // Range between 0.0 and 1.0. If any value other than 0 is returned, |
| 190 | // the software mixer will emulate this capability. |
| 191 | // The GCE implementation always returns 0. |
| 192 | int SetMasterVolume(float volume); |
| 193 | |
| 194 | // Sets the audio mute status for the microphone. |
| 195 | int SetMicMute(bool state); |
| 196 | |
| 197 | // set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode |
| 198 | // is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is |
| 199 | // playing, and AUDIO_MODE_IN_CALL when a call is in progress. |
| 200 | int SetMode(audio_mode_t mode); |
| 201 | |
| 202 | // Sets the global audio parameters. |
| 203 | // TODO(ghartman): Create a sensible implementation. |
| 204 | int SetParameters(const char* kvpairs); |
| 205 | |
| 206 | // Sets the audio volume of a voice call. Range is between 0.0 and 1.0 |
| 207 | int SetVoiceVolume(float volume); |
| 208 | |
| 209 | |
| 210 | private: |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 211 | // HAL 3.0 modifies the signatures of OpenInputStream and OpenOutputStream. |
| 212 | // We don't want to fork the implementation, and we don't want #ifdefs all |
| 213 | // over the code. The current implementation defines OpenInputStream and |
| 214 | // OpenOutputStream with default values for the paramteres that were added, |
| 215 | // and then generates a HAL-specific wrapper to be used in the function |
| 216 | // table. |
| 217 | #if defined(AUDIO_DEVICE_API_VERSION_3_0) |
| 218 | typedef int OpenInputStreamHAL_t( |
| 219 | audio_io_handle_t, audio_devices_t, audio_config*, audio_stream_in**, |
| 220 | audio_input_flags_t, const char*, audio_source_t); |
| 221 | |
| 222 | int OpenInputStreamCurrentHAL( |
| 223 | audio_io_handle_t a, audio_devices_t b, audio_config* c, |
| 224 | audio_stream_in** d, audio_input_flags_t e, const char* f, |
| 225 | audio_source_t g) { |
| 226 | return OpenInputStream(a, b, c, d, e, f, g); |
| 227 | } |
| 228 | |
| 229 | typedef int OpenOutputStreamHAL_t( |
| 230 | audio_io_handle_t, audio_devices_t, audio_output_flags_t, |
| 231 | audio_config*, audio_stream_out**, |
| 232 | const char*); |
| 233 | |
| 234 | int OpenOutputStreamCurrentHAL( |
| 235 | audio_io_handle_t a, audio_devices_t b, audio_output_flags_t c, |
| 236 | audio_config* d, audio_stream_out** e, |
| 237 | const char* f) { |
| 238 | return OpenOutputStream(a, b, c, d, e, f); |
| 239 | } |
| 240 | #else |
| 241 | typedef int OpenInputStreamHAL_t( |
| 242 | audio_io_handle_t, audio_devices_t, audio_config*, audio_stream_in**); |
| 243 | |
| 244 | int OpenInputStreamCurrentHAL( |
| 245 | audio_io_handle_t a, audio_devices_t b, audio_config* c, |
| 246 | audio_stream_in** d) { |
| 247 | return OpenInputStream(a, b, c, d); |
| 248 | } |
| 249 | |
| 250 | typedef int OpenOutputStreamHAL_t( |
| 251 | audio_io_handle_t, audio_devices_t, audio_output_flags_t, |
| 252 | audio_config*, audio_stream_out**); |
| 253 | |
| 254 | int OpenOutputStreamCurrentHAL( |
| 255 | audio_io_handle_t a, audio_devices_t b, audio_output_flags_t c, |
| 256 | audio_config* d, audio_stream_out** e) { |
| 257 | return OpenOutputStream(a, b, c, d, e); |
| 258 | } |
| 259 | #endif |
| 260 | |
| 261 | //TODO(ghartman): Update this when we support 3.0. |
| 262 | #if defined(AUDIO_DEVICE_API_VERSION_2_0) |
| 263 | static const unsigned int version_ = AUDIO_DEVICE_API_VERSION_2_0; |
| 264 | #else |
| 265 | static const unsigned int version_ = AUDIO_DEVICE_API_VERSION_1_0; |
| 266 | #endif |
| 267 | |
Andreas Huber | cc1cd95 | 2018-01-18 12:57:33 -0800 | [diff] [blame^] | 268 | using AudioDataRegionView = vsoc::audio_data::AudioDataRegionView; |
| 269 | AudioDataRegionView *audio_data_rv_ = NULL; |
| 270 | std::unique_ptr<vsoc::RegionWorker> audio_worker_; |
| 271 | |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 272 | // Lock to protect the data below. |
Greg Hartman | 153b106 | 2017-11-11 12:09:21 -0800 | [diff] [blame] | 273 | mutable cvd::Mutex lock_; |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 274 | // State that is managed at the device level. |
| 275 | float voice_volume_; |
| 276 | float master_volume_; |
| 277 | bool master_muted_; |
| 278 | bool mic_muted_; |
| 279 | audio_mode_t mode_; |
| 280 | // There can be multiple input and output streams. This field is used |
| 281 | // to assign each one a unique identifier. |
| 282 | // TODO(ghartman): This can wrap after 2^32 streams. Ideally we should check |
| 283 | // the output_list_ to ensure that the stream number hasn't been assigned. |
| 284 | // However, streams don't really appear and disapper that often. |
| 285 | // We use the same counter for both input and output streams to make things |
| 286 | // a little easier on the client. |
| 287 | uint32_t next_stream_number_; |
| 288 | // List of the currently active output streams. |
| 289 | // Used to clean things up Close() |
| 290 | std::list<GceAudioOutputStream *> output_list_; |
| 291 | // List of the currently active input streams. |
| 292 | // Used to clean things up Close() |
| 293 | typedef std::map<uint32_t, GceAudioInputStream *> input_map_t; |
| 294 | input_map_t input_map_; |
| 295 | |
| 296 | GceAudio() : |
| 297 | audio_hw_device(), |
Tomasz Wiszkowski | b34828c | 2017-09-28 14:03:41 -0700 | [diff] [blame] | 298 | voice_volume_(0.0), |
| 299 | master_volume_(0.0), |
| 300 | master_muted_(false), |
| 301 | mic_muted_(false), |
| 302 | mode_(AUDIO_MODE_NORMAL), |
| 303 | next_stream_number_(1) { } |
| 304 | }; |
| 305 | |
| 306 | } |
| 307 | |