#ifndef ANDROID_AUDIO_HARDWARE_ALSA_H
#define ANDROID_AUDIO_HARDWARE_ALSA_H
+#include <utils/List.h>
#include <hardware_legacy/AudioHardwareBase.h>
#include <alsa/asoundlib.h>
namespace android
{
- class AudioHardwareALSA;
- /**
- * The id of acoustics module
- */
-#define ACOUSTICS_HARDWARE_MODULE_ID "acoustics"
-#define ACOUSTICS_HARDWARE_NAME "name"
-
- struct acoustic_device_t {
- hw_device_t common;
-
- /**
- * Set the provided acoustics for a particular ALSA pcm device.
- *
- * Returns: 0 on succes, error code on failure.
- */
- status_t (*set_acoustics)(snd_pcm_t *, AudioSystem::audio_in_acoustics);
-
- /**
- * Read callback with PCM data so that filtering may be applied.
- *
- * Returns: frames filtered on success, error code on failure.
- */
- ssize_t (*filter)(snd_pcm_t *, void *, ssize_t);
- };
-
- // ----------------------------------------------------------------------------
-
- class ALSAMixer
- {
- public:
- ALSAMixer();
- virtual ~ALSAMixer();
+class AudioHardwareALSA;
+
+/**
+ * The id of ALSA module
+ */
+#define ALSA_HARDWARE_MODULE_ID "alsa"
+#define ALSA_HARDWARE_NAME "alsa"
+
+struct alsa_device_t;
+
+struct alsa_handle_t {
+ alsa_device_t * module;
+ uint32_t devices;
+ uint32_t curDev;
+ int curMode;
+ snd_pcm_t * handle;
+ snd_pcm_format_t format;
+ uint32_t channels;
+ uint32_t sampleRate;
+ unsigned int latency; // Delay in usec
+ unsigned int bufferSize; // Size of sample buffer
+ void * modPrivate;
+};
+
+typedef List<alsa_handle_t> ALSAHandleList;
+
+struct alsa_device_t {
+ hw_device_t common;
+
+ status_t (*init)(alsa_device_t *, ALSAHandleList &);
+ status_t (*open)(alsa_handle_t *, uint32_t, int);
+ status_t (*close)(alsa_handle_t *);
+ status_t (*route)(alsa_handle_t *, uint32_t, int);
+};
+
+/**
+ * The id of acoustics module
+ */
+#define ACOUSTICS_HARDWARE_MODULE_ID "acoustics"
+#define ACOUSTICS_HARDWARE_NAME "acoustics"
- bool isValid() { return !!mMixer[SND_PCM_STREAM_PLAYBACK]; }
- status_t setMasterVolume(float volume);
- status_t setMasterGain(float gain);
+struct acoustic_device_t {
+ hw_device_t common;
- status_t setVolume(uint32_t device, float volume);
- status_t setGain(uint32_t device, float gain);
+ // Required methods...
+ status_t (*use_handle)(acoustic_device_t *, alsa_handle_t *);
+ status_t (*cleanup)(acoustic_device_t *);
- status_t setCaptureMuteState(uint32_t device, bool state);
- status_t getCaptureMuteState(uint32_t device, bool *state);
- status_t setPlaybackMuteState(uint32_t device, bool state);
- status_t getPlaybackMuteState(uint32_t device, bool *state);
+ status_t (*set_params)(acoustic_device_t *, AudioSystem::audio_in_acoustics, void *);
- private:
- snd_mixer_t *mMixer[SND_PCM_STREAM_LAST+1];
- };
+ // Optional methods...
+ ssize_t (*read)(acoustic_device_t *, void *, size_t);
+ ssize_t (*write)(acoustic_device_t *, const void *, size_t);
+ status_t (*recover)(acoustic_device_t *, int);
- class ALSAControl
- {
- public:
- ALSAControl(const char *device = "default");
- virtual ~ALSAControl();
+ void * modPrivate;
+};
+
+// ----------------------------------------------------------------------------
+
+class ALSAMixer
+{
+public:
+ ALSAMixer();
+ virtual ~ALSAMixer();
+
+ bool isValid() { return !!mMixer[SND_PCM_STREAM_PLAYBACK]; }
+ status_t setMasterVolume(float volume);
+ status_t setMasterGain(float gain);
+
+ status_t setVolume(uint32_t device, float left, float right);
+ status_t setGain(uint32_t device, float gain);
+
+ status_t setCaptureMuteState(uint32_t device, bool state);
+ status_t getCaptureMuteState(uint32_t device, bool *state);
+ status_t setPlaybackMuteState(uint32_t device, bool state);
+ status_t getPlaybackMuteState(uint32_t device, bool *state);
+
+private:
+ snd_mixer_t * mMixer[SND_PCM_STREAM_LAST+1];
+};
+
+class ALSAControl
+{
+public:
+ ALSAControl(const char *device = "hw:00");
+ virtual ~ALSAControl();
- status_t get(const char *name, unsigned int &value, int index = 0);
- status_t set(const char *name, unsigned int value, int index = -1);
+ status_t get(const char *name, unsigned int &value, int index = 0);
+ status_t set(const char *name, unsigned int value, int index = -1);
- private:
- snd_ctl_t *mHandle;
- };
+ status_t set(const char *name, const char *);
- class ALSAStreamOps
+private:
+ snd_ctl_t * mHandle;
+};
+
+class ALSAStreamOps
+{
+public:
+ ALSAStreamOps(AudioHardwareALSA *parent, alsa_handle_t *handle);
+ virtual ~ALSAStreamOps();
+
+ status_t set(int *format, uint32_t *channels, uint32_t *rate);
+
+ status_t setParameters(const String8& keyValuePairs);
+ String8 getParameters(const String8& keys);
+
+ uint32_t sampleRate() const;
+ size_t bufferSize() const;
+ int format() const;
+ uint32_t channels() const;
+
+ status_t open(int mode);
+ void close();
+
+protected:
+ friend class AudioHardwareALSA;
+
+ acoustic_device_t *acoustics();
+ ALSAMixer *mixer();
+
+ AudioHardwareALSA * mParent;
+ alsa_handle_t * mHandle;
+
+ Mutex mLock;
+ bool mPowerLock;
+};
+
+// ----------------------------------------------------------------------------
+
+class AudioStreamOutALSA : public AudioStreamOut, public ALSAStreamOps
+{
+public:
+ AudioStreamOutALSA(AudioHardwareALSA *parent, alsa_handle_t *handle);
+ virtual ~AudioStreamOutALSA();
+
+ virtual uint32_t sampleRate() const
{
- public:
- struct StreamDefaults
- {
- const char * devicePrefix;
- snd_pcm_stream_t direction; // playback or capture
- snd_pcm_format_t format;
- int channels;
- uint32_t sampleRate;
- unsigned int latency; // Delay in usec
- unsigned int bufferSize; // Size of sample buffer
- };
-
- ALSAStreamOps(AudioHardwareALSA *parent);
- virtual ~ALSAStreamOps();
-
- status_t set(int format,
- int channels,
- uint32_t rate);
- virtual uint32_t sampleRate() const;
- status_t sampleRate(uint32_t rate);
- virtual size_t bufferSize() const;
- virtual int format() const;
- virtual int channelCount() const;
- status_t channelCount(int channels);
- const char *streamName();
- virtual status_t setDevice(int mode, uint32_t device);
-
- const char *deviceName(int mode, uint32_t device);
-
- protected:
- friend class AudioStreamOutALSA;
- friend class AudioStreamInALSA;
-
- status_t open(int mode, uint32_t device);
- void close();
- status_t setSoftwareParams();
- status_t setPCMFormat(snd_pcm_format_t format);
- status_t setHardwareResample(bool resample);
-
- void setStreamDefaults(StreamDefaults *dev) {
- mDefaults = dev;
- }
-
- private:
- AudioHardwareALSA *mParent;
- snd_pcm_t *mHandle;
- snd_pcm_hw_params_t *mHardwareParams;
- snd_pcm_sw_params_t *mSoftwareParams;
- int mMode;
- uint32_t mDevice;
-
- StreamDefaults *mDefaults;
- };
-
- // ----------------------------------------------------------------------------
-
- class AudioStreamOutALSA : public AudioStreamOut, public ALSAStreamOps
+ return ALSAStreamOps::sampleRate();
+ }
+
+ virtual size_t bufferSize() const
{
- public:
- AudioStreamOutALSA(AudioHardwareALSA *parent);
- virtual ~AudioStreamOutALSA();
+ return ALSAStreamOps::bufferSize();
+ }
- status_t set(int format = 0,
- int channelCount = 0,
- uint32_t sampleRate = 0) {
- return ALSAStreamOps::set(format, channelCount, sampleRate);
- }
+ virtual uint32_t channels() const;
- virtual uint32_t sampleRate() const
- {
- return ALSAStreamOps::sampleRate();
- }
+ virtual int format() const
+ {
+ return ALSAStreamOps::format();
+ }
- virtual size_t bufferSize() const
- {
- return ALSAStreamOps::bufferSize();
- }
+ virtual uint32_t latency() const;
- virtual int channelCount() const;
+ virtual ssize_t write(const void *buffer, size_t bytes);
+ virtual status_t dump(int fd, const Vector<String16>& args);
- virtual int format() const
- {
- return ALSAStreamOps::format();
- }
+ status_t setVolume(float left, float right);
- virtual uint32_t latency() const;
+ virtual status_t standby();
- virtual ssize_t write(const void *buffer, size_t bytes);
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setDevice(int mode, uint32_t newDevice);
+ virtual status_t setParameters(const String8& keyValuePairs) {
+ return ALSAStreamOps::setParameters(keyValuePairs);
+ }
- status_t setVolume(float volume);
+ virtual String8 getParameters(const String8& keys) {
+ return ALSAStreamOps::getParameters(keys);
+ }
- status_t standby();
- bool isStandby();
- };
+ // return the number of audio frames written by the audio dsp to DAC since
+ // the output has exited standby
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
- class AudioStreamInALSA : public AudioStreamIn, public ALSAStreamOps
+ status_t open(int mode);
+ status_t close();
+
+private:
+ uint32_t mFrameCount;
+};
+
+class AudioStreamInALSA : public AudioStreamIn, public ALSAStreamOps
+{
+public:
+ AudioStreamInALSA(AudioHardwareALSA *parent,
+ alsa_handle_t *handle,
+ AudioSystem::audio_in_acoustics audio_acoustics);
+ virtual ~AudioStreamInALSA();
+
+ virtual uint32_t sampleRate() const
+ {
+ return ALSAStreamOps::sampleRate();
+ }
+
+ virtual size_t bufferSize() const
+ {
+ return ALSAStreamOps::bufferSize();
+ }
+
+ virtual uint32_t channels() const
{
- public:
- AudioStreamInALSA(AudioHardwareALSA *parent,
- AudioSystem::audio_in_acoustics acoustics);
- virtual ~AudioStreamInALSA();
+ return ALSAStreamOps::channels();
+ }
- status_t set(int format = 0,
- int channelCount = 0,
- uint32_t sampleRate = 0) {
- return ALSAStreamOps::set(format, channelCount, sampleRate);
- }
+ virtual int format() const
+ {
+ return ALSAStreamOps::format();
+ }
+
+ virtual ssize_t read(void* buffer, ssize_t bytes);
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ virtual status_t setGain(float gain);
+
+ virtual status_t standby();
- virtual uint32_t sampleRate() {
- return ALSAStreamOps::sampleRate();
- }
+ virtual status_t setParameters(const String8& keyValuePairs)
+ {
+ return ALSAStreamOps::setParameters(keyValuePairs);
+ }
- virtual size_t bufferSize() const
- {
- return ALSAStreamOps::bufferSize();
- }
+ virtual String8 getParameters(const String8& keys)
+ {
+ return ALSAStreamOps::getParameters(keys);
+ }
- virtual int channelCount() const
- {
- return ALSAStreamOps::channelCount();
- }
+ // Return the amount of input frames lost in the audio driver since the last call of this function.
+ // Audio driver is expected to reset the value to 0 and restart counting upon returning the current value by this function call.
+ // Such loss typically occurs when the user space process is blocked longer than the capacity of audio driver buffers.
+ // Unit: the number of input audio frames
+ virtual unsigned int getInputFramesLost() const;
- virtual int format() const
- {
- return ALSAStreamOps::format();
- }
+ status_t setAcousticParams(void* params);
- virtual ssize_t read(void* buffer, ssize_t bytes);
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setDevice(int mode, uint32_t newDevice);
+ status_t open(int mode);
+ status_t close();
- virtual status_t setGain(float gain);
+private:
+ void resetFramesLost();
- virtual status_t standby();
+ unsigned int mFramesLost;
+ AudioSystem::audio_in_acoustics mAcoustics;
+};
- private:
- AudioSystem::audio_in_acoustics mAcoustics;
- };
+class AudioHardwareALSA : public AudioHardwareBase
+{
+public:
+ AudioHardwareALSA();
+ virtual ~AudioHardwareALSA();
- class AudioHardwareALSA : public AudioHardwareBase
+ /**
+ * check to see if the audio hardware interface has been initialized.
+ * return status based on values defined in include/utils/Errors.h
+ */
+ virtual status_t initCheck();
+
+ /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */
+ virtual status_t setVoiceVolume(float volume);
+
+ /**
+ * set the audio volume for all audio activities other than voice call.
+ * Range between 0.0 and 1.0. If any value other than NO_ERROR is returned,
+ * the software mixer will emulate this capability.
+ */
+ virtual status_t setMasterVolume(float volume);
+
+ /**
+ * setMode is called when the audio mode changes. NORMAL mode is for
+ * standard audio playback, RINGTONE when a ringtone is playing, and IN_CALL
+ * when a call is in progress.
+ */
+ virtual status_t setMode(int mode);
+
+ // mic mute
+ virtual status_t setMicMute(bool state);
+ virtual status_t getMicMute(bool* state);
+
+ // set/get global audio parameters
+ //virtual status_t setParameters(const String8& keyValuePairs);
+ //virtual String8 getParameters(const String8& keys);
+
+ // Returns audio input buffer size according to parameters passed or 0 if one of the
+ // parameters is not supported
+ //virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channels);
+
+ /** This method creates and opens the audio hardware output stream */
+ virtual AudioStreamOut* openOutputStream(
+ uint32_t devices,
+ int *format=0,
+ uint32_t *channels=0,
+ uint32_t *sampleRate=0,
+ status_t *status=0);
+ virtual void closeOutputStream(AudioStreamOut* out);
+
+ /** This method creates and opens the audio hardware input stream */
+ virtual AudioStreamIn* openInputStream(
+ uint32_t devices,
+ int *format,
+ uint32_t *channels,
+ uint32_t *sampleRate,
+ status_t *status,
+ AudioSystem::audio_in_acoustics acoustics);
+ virtual void closeInputStream(AudioStreamIn* in);
+
+ /**This method dumps the state of the audio hardware */
+ //virtual status_t dumpState(int fd, const Vector<String16>& args);
+
+ static AudioHardwareInterface* create();
+
+ int mode()
{
- public:
- AudioHardwareALSA();
- virtual ~AudioHardwareALSA();
-
- /**
- * check to see if the audio hardware interface has been initialized.
- * return status based on values defined in include/utils/Errors.h
- */
- virtual status_t initCheck();
-
- /**
- * put the audio hardware into standby mode to conserve power. Returns
- * status based on include/utils/Errors.h
- */
- virtual status_t standby();
-
- /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */
- virtual status_t setVoiceVolume(float volume);
-
- /**
- * set the audio volume for all audio activities other than voice call.
- * Range between 0.0 and 1.0. If any value other than NO_ERROR is returned,
- * the software mixer will emulate this capability.
- */
- virtual status_t setMasterVolume(float volume);
-
- // mic mute
- virtual status_t setMicMute(bool state);
- virtual status_t getMicMute(bool* state);
-
- /** This method creates and opens the audio hardware output stream */
- virtual AudioStreamOut* openOutputStream(
- int format=0,
- int channelCount=0,
- uint32_t sampleRate=0,
- status_t *status=0);
-
- /** This method creates and opens the audio hardware input stream */
- virtual AudioStreamIn* openInputStream(
- int inputSource,
- int format,
- int channelCount,
- uint32_t sampleRate,
- status_t *status,
- AudioSystem::audio_in_acoustics acoustics);
-
- protected:
- /**
- * doRouting actually initiates the routing. A call to setRouting
- * or setMode may result in a routing change. The generic logic calls
- * doRouting when required. If the device has any special requirements these
- * methods can be overriden.
- */
- virtual status_t doRouting();
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- friend class AudioStreamOutALSA;
- friend class AudioStreamInALSA;
-
- ALSAMixer *mMixer;
- AudioStreamOutALSA *mOutput;
- AudioStreamInALSA *mInput;
-
- acoustic_device_t *mAcousticDevice;
-
- private:
- Mutex mLock;
- bool mPowerLock;
- };
-
- // ----------------------------------------------------------------------------
+ return mMode;
+ }
+
+protected:
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ friend class AudioStreamOutALSA;
+ friend class AudioStreamInALSA;
+ friend class ALSAStreamOps;
+
+ ALSAMixer * mMixer;
+
+ alsa_device_t * mALSADevice;
+ acoustic_device_t * mAcousticDevice;
+
+ ALSAHandleList mDeviceList;
+
+private:
+ Mutex mLock;
+};
+
+// ----------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_AUDIO_HARDWARE_ALSA_H