| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #pragma once |
| |
| #include <list> |
| #include <map> |
| |
| #include "common/libs/fs/shared_fd.h" |
| #include "common/libs/threads/pthread.h" |
| #include "guest/commands/audio/audio_hal.h" |
| #include "guest/commands/audio/vsoc_audio_input_stream.h" |
| #include "guest/commands/audio/vsoc_audio_message.h" |
| #include "guest/libs/platform_support/api_level_fixes.h" |
| |
| namespace avd { |
| |
| class GceAudioInputStream; |
| class GceAudioOutputStream; |
| |
| class GceAudio : public audio_hw_device { |
| public: |
| // This common code manipulates the parameters of input and output streams. |
| static int SetStreamParameters(struct audio_stream *, const char *); |
| |
| ~GceAudio(); |
| |
| // Non-HAL methods that are part of the GCE implementation. |
| // Most of these are used by the input and output streams. |
| |
| // Returns true if the microphone is muted. Used by input streams. |
| bool IsMicrophoneMuted() { |
| avd::LockGuard<avd::Mutex> guard(lock_); |
| return mic_muted_; |
| } |
| |
| // Retrieves the SharedFD of the process accepting audio data. |
| // Returns a non-open fd if no process is listening (the normal case). |
| avd::SharedFD GetAudioFd(); |
| |
| // Send a message to the connected streamer. |
| // Returns: |
| // 0 if there is no streamer. |
| // >0 if the message was sent. |
| // -1 if there was an error. |
| ssize_t SendMsg(const msghdr&, int flags); |
| |
| // Sends a stream update to the connected streamer. |
| // Stream updates have no frames. Use SendMsg if the message has frames. |
| // 0 if there is no streamer. |
| // >0 if the message was sent. |
| // -1 if there was an error. |
| ssize_t SendStreamUpdate( |
| const gce_audio_message& stream_info, int flags); |
| |
| // Callbacks for the Android audio_module HAL interface. |
| // Most of the comments below are copied from |
| // libhardware/include/hardware/audio.h |
| // |
| // Where the is a conflict the comments there apply. |
| // By default these methods return 0 on success -<errno> for failure. |
| |
| // Opens the device. |
| static int Open(const hw_module_t* module, const char* name, |
| hw_device_t** device); |
| |
| // Closes the device, closing any open input streams and output streams. |
| int Close(); |
| |
| // Closes the input stream, throwing away any data in the buffer. |
| void CloseInputStream(audio_stream_in* stream); |
| |
| // Closes the output stream without waiting for the buffer to clear. |
| void CloseOutputStream(audio_stream_out* stream); |
| |
| // Creates an audio patch between several source and sink ports. |
| // The handle is allocated by the HAL and should be unique for this |
| // audio HAL module. |
| // TODO(ghartman): Implement this as part of HAL 3.0 |
| //int CreateAudioPatch(unsigned int num_sources, |
| // const struct audio_port_config *sources, |
| // unsigned int num_sinks, |
| // const struct audio_port_config *sinks, |
| // audio_patch_handle_t *handle); |
| |
| // dumps the state of the audio hardware to the given fd. |
| // This information can be retrieved using the dumpsys utility. |
| int Dump(int fd) const; |
| |
| // Fills the list of supported attributes for a given audio port. |
| // As input, "port" contains the information (type, role, address etc...) |
| // needed by the HAL to identify the port. |
| // As output, "port" contains possible attributes (sampling rates, formats, |
| // channel masks, gain controllers...) for this port. |
| // TODO(ghartman): Implement this as part of HAL 3.0 |
| // int GetAudioPort(struct audio_port *port); |
| |
| // Sets audio port configuration |
| // TODO(ghartman): Implement this as part of HAL 3.0 |
| // int SetAudioPortConfig(const struct audio_port_config *config); |
| |
| size_t GetInputBufferSize(const audio_config*) const; |
| |
| // Gets the current master volume value for the HAL, if the HAL supports |
| // master volume control. AudioFlinger will query this value from the |
| // primary audio HAL when the service starts and use the value for setting |
| // the initial master volume across all HALs. HALs which do not support |
| // this method may leave it set to NULL. |
| int GetMasterVolume(float* /*volume*/); |
| |
| // Get the current master mute status for the HAL, if the HAL supports |
| // master mute control. AudioFlinger will query this value from the primary |
| // audio HAL when the service starts and use the value for setting the |
| // initial master mute across all HALs. HALs which do not support this |
| // method may leave it set to NULL. |
| int GetMasterMute(bool* muted); |
| |
| // Gets the audio mute status for the microphone. |
| int GetMicMute(bool* state) const; |
| |
| // Retrieves the global audio parameters. |
| // TODO(ghartman): Implement this. |
| char* GetParameters(const char* keys) const; |
| |
| // Enumerates what devices are supported by each audio_hw_device |
| // implementation. |
| // Return value is a bitmask of 1 or more values of audio_devices_t |
| // used by audio flinger. |
| // NOTE: audio HAL implementations starting with |
| // AUDIO_DEVICE_API_VERSION_2_0 do not implement this function. |
| // AUDIO_DEVICE_API_VERSION_2_0 was the current version as of JB-MR1 |
| // All supported devices should be listed in audio_policy.conf |
| // file and the audio policy manager must choose the appropriate |
| // audio module based on information in this file. |
| uint32_t GetSupportedDevices() const; |
| |
| // Checks to see if the audio hardware interface has been initialized. |
| // Always returns 0 to indicate success, but -ENODEV is also allowed to |
| // indicate failure. |
| int InitCheck() const; |
| |
| // Creates an additional hardware input stream. |
| // Additional parameters were added in the 3.0 version of the HAL. |
| // These defaults make it easier to implement a cross-branch device. |
| int OpenInputStream( |
| audio_io_handle_t handle, |
| audio_devices_t devices, audio_config *config, |
| audio_stream_in **stream_in, |
| audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE, |
| const char* address = 0, |
| audio_source_t source = AUDIO_SOURCE_DEFAULT); |
| |
| // Creates an additional output stream. |
| // The "address" parameter qualifies the "devices" audio device type if |
| // needed. On GCE we ignore it for now because we simulate a single SoC |
| // hw devices. |
| // |
| // The format format depends on the device type: |
| // Bluetooth devices use the MAC address of the device in the form |
| // "00:11:22:AA:BB:CC" |
| // USB devices use the ALSA card and device numbers in the form |
| // "card=X;device=Y" |
| // Other devices may use a number or any other string. |
| int 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* address = 0); |
| |
| // Releases an audio patch. |
| // TODO(ghartman): Implement this as part of HAL 3.0 |
| //int ReleaseAudioPatch(audio_patch_handle_t handle); |
| |
| // Sets the audio mute status for all audio activities. If any value other |
| // than 0 is returned, the software mixer will emulate this capability. |
| // The GCE implementation always returns 0. |
| int SetMasterMute(bool muted); |
| |
| // Sets the audio volume for all audio activities other than voice call. |
| // Range between 0.0 and 1.0. If any value other than 0 is returned, |
| // the software mixer will emulate this capability. |
| // The GCE implementation always returns 0. |
| int SetMasterVolume(float volume); |
| |
| // Sets the audio mute status for the microphone. |
| int SetMicMute(bool state); |
| |
| // set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode |
| // is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is |
| // playing, and AUDIO_MODE_IN_CALL when a call is in progress. |
| int SetMode(audio_mode_t mode); |
| |
| // Sets the global audio parameters. |
| // TODO(ghartman): Create a sensible implementation. |
| int SetParameters(const char* kvpairs); |
| |
| // Sets the audio volume of a voice call. Range is between 0.0 and 1.0 |
| int SetVoiceVolume(float volume); |
| |
| |
| private: |
| // Main routine for a thread that listens for incoming streamer connections. |
| void* Listener(); |
| // HAL 3.0 modifies the signatures of OpenInputStream and OpenOutputStream. |
| // We don't want to fork the implementation, and we don't want #ifdefs all |
| // over the code. The current implementation defines OpenInputStream and |
| // OpenOutputStream with default values for the paramteres that were added, |
| // and then generates a HAL-specific wrapper to be used in the function |
| // table. |
| #if defined(AUDIO_DEVICE_API_VERSION_3_0) |
| typedef int OpenInputStreamHAL_t( |
| audio_io_handle_t, audio_devices_t, audio_config*, audio_stream_in**, |
| audio_input_flags_t, const char*, audio_source_t); |
| |
| int OpenInputStreamCurrentHAL( |
| audio_io_handle_t a, audio_devices_t b, audio_config* c, |
| audio_stream_in** d, audio_input_flags_t e, const char* f, |
| audio_source_t g) { |
| return OpenInputStream(a, b, c, d, e, f, g); |
| } |
| |
| typedef int OpenOutputStreamHAL_t( |
| audio_io_handle_t, audio_devices_t, audio_output_flags_t, |
| audio_config*, audio_stream_out**, |
| const char*); |
| |
| int OpenOutputStreamCurrentHAL( |
| audio_io_handle_t a, audio_devices_t b, audio_output_flags_t c, |
| audio_config* d, audio_stream_out** e, |
| const char* f) { |
| return OpenOutputStream(a, b, c, d, e, f); |
| } |
| #else |
| typedef int OpenInputStreamHAL_t( |
| audio_io_handle_t, audio_devices_t, audio_config*, audio_stream_in**); |
| |
| int OpenInputStreamCurrentHAL( |
| audio_io_handle_t a, audio_devices_t b, audio_config* c, |
| audio_stream_in** d) { |
| return OpenInputStream(a, b, c, d); |
| } |
| |
| typedef int OpenOutputStreamHAL_t( |
| audio_io_handle_t, audio_devices_t, audio_output_flags_t, |
| audio_config*, audio_stream_out**); |
| |
| int OpenOutputStreamCurrentHAL( |
| audio_io_handle_t a, audio_devices_t b, audio_output_flags_t c, |
| audio_config* d, audio_stream_out** e) { |
| return OpenOutputStream(a, b, c, d, e); |
| } |
| #endif |
| |
| //TODO(ghartman): Update this when we support 3.0. |
| #if defined(AUDIO_DEVICE_API_VERSION_2_0) |
| static const unsigned int version_ = AUDIO_DEVICE_API_VERSION_2_0; |
| #else |
| static const unsigned int version_ = AUDIO_DEVICE_API_VERSION_1_0; |
| #endif |
| |
| // Thread to handle new connections. |
| pthread_t listener_thread_; |
| // Event to indicate that the listener thread should terminate. |
| avd::SharedFD terminate_listener_thread_event_; |
| // The listener socket, which is polled for new connections. |
| // TODO(ghartman): Consider using a thread. |
| avd::SharedFD audio_listener_socket_; |
| // Lock to protect the data below. |
| mutable avd::Mutex lock_; |
| // The data socket for the current streamer. Typically -1. |
| // The behavior of the HAL should not be affected by the presence or absence |
| // of the streamer. |
| avd::SharedFD audio_data_socket_; |
| // State that is managed at the device level. |
| float voice_volume_; |
| float master_volume_; |
| bool master_muted_; |
| bool mic_muted_; |
| audio_mode_t mode_; |
| // There can be multiple input and output streams. This field is used |
| // to assign each one a unique identifier. |
| // TODO(ghartman): This can wrap after 2^32 streams. Ideally we should check |
| // the output_list_ to ensure that the stream number hasn't been assigned. |
| // However, streams don't really appear and disapper that often. |
| // We use the same counter for both input and output streams to make things |
| // a little easier on the client. |
| uint32_t next_stream_number_; |
| // List of the currently active output streams. |
| // Used to clean things up Close() |
| std::list<GceAudioOutputStream *> output_list_; |
| // List of the currently active input streams. |
| // Used to clean things up Close() |
| typedef std::map<uint32_t, GceAudioInputStream *> input_map_t; |
| input_map_t input_map_; |
| |
| GceAudio() : |
| audio_hw_device(), |
| terminate_listener_thread_event_(avd::SharedFD::Event()), |
| voice_volume_(0.0), |
| master_volume_(0.0), |
| master_muted_(false), |
| mic_muted_(false), |
| mode_(AUDIO_MODE_NORMAL), |
| next_stream_number_(1) { } |
| }; |
| |
| } |
| |