blob: 24d4a162c47b3e766bc7ef02542f0138859caf28 [file] [log] [blame]
/*
** Copyright 2008-2010, 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.
*/
#ifndef ANDROID_AUDIO_HARDWARE_H
#define ANDROID_AUDIO_HARDWARE_H
#include <stdint.h>
#include <sys/types.h>
#include <utils/threads.h>
#include <utils/SortedVector.h>
#include <hardware_legacy/AudioHardwareBase.h>
#include "AudioPostProcessor.h"
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
extern "C" {
#include "rate_conv.h"
}
#endif
namespace android_audio_legacy {
using android::AutoMutex;
using android::Mutex;
using android::SortedVector;
#include <linux/cpcap_audio.h>
#include <linux/tegra_audio.h>
#define AUDIO_HW_OUT_SAMPLERATE 44100
#define AUDIO_HW_NUM_OUT_BUF 2
#define AUDIO_HW_OUT_LATENCY_MS 0
// FIXME: this is a workaround for issue 3387419 with impact on latency
// to be removed when root cause is fixed
#define AUDIO_HW_NUM_OUT_BUF_LONG 4
#define AUDIO_HW_IN_SAMPLERATE 11025 // Default audio input sample rate
#define AUDIO_HW_IN_CHANNELS (AudioSystem::CHANNEL_IN_MONO) // Default audio input channel mask
#define AUDIO_HW_IN_BUFFERSIZE (4096) // Default audio input buffer size
#define AUDIO_HW_IN_FORMAT (AudioSystem::PCM_16_BIT) // Default audio input sample format
enum {
AUDIO_HW_GAIN_SPKR_GAIN = 0,
AUDIO_HW_GAIN_MIC_GAIN,
AUDIO_HW_GAIN_NUM_DIRECTIONS
};
enum {
AUDIO_HW_GAIN_USECASE_VOICE= 0,
AUDIO_HW_GAIN_USECASE_MM,
AUDIO_HW_GAIN_USECASE_VOICE_REC,
AUDIO_HW_GAIN_NUM_USECASES
};
enum {
AUDIO_HW_GAIN_EARPIECE = 0,
AUDIO_HW_GAIN_SPEAKERPHONE,
AUDIO_HW_GAIN_HEADSET_W_MIC,
AUDIO_HW_GAIN_MONO_HEADSET,
AUDIO_HW_GAIN_HEADSET_NO_MIC,
AUDIO_HW_GAIN_EMU_DEVICE,
AUDIO_HW_GAIN_RSVD1,
AUDIO_HW_GAIN_RSVD2,
AUDIO_HW_GAIN_RSVD3,
AUDIO_HW_GAIN_RSVD4,
AUDIO_HW_GAIN_RSVD5,
AUDIO_HW_GAIN_NUM_PATHS
};
enum input_state {
AUDIO_STREAM_IDLE,
AUDIO_STREAM_CONFIG_REQ,
AUDIO_STREAM_NEW_RATE_REQ,
AUDIO_STREAM_CONFIGURED
};
class AudioHardware : public AudioHardwareBase
{
class AudioStreamOutTegra;
class AudioStreamInTegra;
class AudioStreamSrc;
public:
// AudioHardwareInterface
AudioHardware();
virtual ~AudioHardware();
virtual status_t initCheck();
virtual status_t setVoiceVolume(float volume);
virtual status_t setMasterVolume(float volume);
virtual status_t setMode(int mode);
// mic mute
virtual status_t setMicMute(bool state);
virtual status_t getMicMute(bool* state);
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
// create I/O streams
virtual AudioStreamOut* openOutputStream(
uint32_t devices,
int *format=0,
uint32_t *channels=0,
uint32_t *sampleRate=0,
status_t *status=0);
virtual AudioStreamIn* openInputStream(
uint32_t devices,
int *format,
uint32_t *channels,
uint32_t *sampleRate,
status_t *status,
AudioSystem::audio_in_acoustics acoustics);
virtual void closeOutputStream(AudioStreamOut* out);
virtual void closeInputStream(AudioStreamIn* in);
virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
// AudioHardwareBase provides default implementation
//virtual status_t dumpState(int fd, const Vector<String16>& args);
// added by AudioHardware
status_t init();
// voice processing IDs for mEcnsRequested and mEcnsEnabled
enum {
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
PREPROC_AEC = AudioPostProcessor::AEC, // AEC is enabled
PREPROC_NS = AudioPostProcessor::NS, // NS is enabled
#else
PREPROC_AEC = 0x1, // AEC is enabled
PREPROC_NS = 0x2, // NS is enabled
#endif
};
void setEcnsRequested_l(int ecns, bool enabled);
bool isEcRequested() { return !!(mEcnsRequested & PREPROC_AEC); }
protected:
// AudioHardwareBase provides default implementation
//virtual bool isModeInCall(int mode);
//virtual bool isInCall();
// AudioHardwareInterface
virtual status_t dump(int fd, const Vector<String16>& args);
// added by AudioHardware
int getActiveInputRate();
private:
status_t dumpInternals(int fd, const Vector<String16>& args);
uint32_t getInputSampleRate(uint32_t sampleRate);
status_t doStandby(int stop_fd, bool output, bool enable);
status_t doRouting_l();
status_t doRouting();
status_t setVolume_l(float v, int usecase);
uint8_t getGain(int direction, int usecase);
void readHwGainFile();
AudioStreamInTegra* getActiveInput_l();
status_t setMicMute_l(bool state);
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
class AudioStreamSrc {
public:
AudioStreamSrc();
~AudioStreamSrc();
inline int inRate() {return mSrcInRate;};
inline int outRate() {return mSrcOutRate;};
inline bool initted() {return mSrcInitted;};
void init(int inRate, int outRate);
inline void deinit() {mSrcInitted = false;};
SRC_IO_T mIoData;
inline void srcConvert() { rate_convert(&mIoData, &mSrcObj, 0x0800); };
private:
SRC_OBJ_T mSrcObj;
char * mSrcBuffer;
SRC_INIT_T mSrcInit;
int mSrcInRate;
int mSrcOutRate;
bool mSrcInitted;
};
#endif
class AudioStreamOutTegra : public AudioStreamOut {
public:
AudioStreamOutTegra();
virtual ~AudioStreamOutTegra();
status_t init();
status_t initCheck();
void setDriver_l(bool speaker, bool bluetooth, bool spdif, int sampleRate);
status_t set(AudioHardware* mHardware,
uint32_t devices,
int *pFormat,
uint32_t *pChannels,
uint32_t *pRate);
virtual uint32_t sampleRate() const { return AUDIO_HW_OUT_SAMPLERATE; }
// must be 32-bit aligned - driver only seems to like 4800
virtual size_t bufferSize() const { return 4096; }
virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
virtual int format() const { return AudioSystem::PCM_16_BIT; }
virtual uint32_t latency() const { return (1000*AUDIO_HW_NUM_OUT_BUF_LONG*(bufferSize()/frameSize()))/sampleRate()+AUDIO_HW_OUT_LATENCY_MS; }
virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; }
virtual ssize_t write(const void* buffer, size_t bytes);
void flush();
void flush_l();
virtual status_t standby();
status_t online_l();
virtual status_t dump(int fd, const Vector<String16>& args);
bool getStandby();
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
uint32_t devices() { return mDevices; }
virtual status_t getRenderPosition(uint32_t *dspFrames);
void lock() { mSleepReq = true; mLock.lock(); mSleepReq = false; }
void unlock() { mLock.unlock(); }
bool isLocked() { return mLocked; }
void setNumBufs(int numBufs);
void lockFd() { mFdLock.lock(); }
void unlockFd() { mFdLock.unlock(); }
int mBtFdIoCtl;
private:
AudioHardware* mHardware;
Mutex mLock;
int mFd;
int mFdCtl;
int mBtFd;
int mBtFdCtl;
int mSpdifFd;
int mSpdifFdCtl;
int mStartCount;
int mRetryCount;
uint32_t mDevices;
Mutex mFdLock;
bool mIsSpkrEnabled;
bool mIsBtEnabled;
bool mIsSpdifEnabled;
bool mIsSpkrEnabledReq;
bool mIsBtEnabledReq;
bool mIsSpdifEnabledReq;
int16_t mSpareSample;
bool mHaveSpareSample;
int mState;
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
AudioStreamSrc mSrc;
#endif
bool mLocked; // setDriver() doesn't have to lock if true
int mDriverRate;
bool mInit;
bool mSleepReq;
};
class AudioStreamInTegra : public AudioStreamIn {
public:
AudioStreamInTegra();
virtual ~AudioStreamInTegra();
status_t set(AudioHardware* mHardware,
uint32_t devices,
int *pFormat,
uint32_t *pChannels,
uint32_t *pRate,
AudioSystem::audio_in_acoustics acoustics);
virtual size_t bufferSize() const { return mBufferSize; }
virtual uint32_t channels() const { return mChannels; }
virtual int format() const { return mFormat; }
virtual uint32_t sampleRate() const { return mSampleRate; }
virtual status_t setGain(float gain) { return INVALID_OPERATION; }
virtual ssize_t read(void* buffer, ssize_t bytes);
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t standby();
virtual status_t online_l();
bool getStandby() const;
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
virtual unsigned int getInputFramesLost() const;
virtual status_t addAudioEffect(effect_handle_t effect);
virtual status_t removeAudioEffect(effect_handle_t effect);
uint32_t devices() { return mDevices; }
void setDriver_l(bool mic, bool bluetooth, int sampleRate);
int source() const { return mSource; }
void lock() { mSleepReq = true; mLock.lock(); mSleepReq = false; }
void unlock() { mLock.unlock(); }
bool isLocked() { return mLocked; }
void stop_l();
void lockFd() { mFdLock.lock(); }
void unlockFd() { mFdLock.unlock(); }
private:
void reopenReconfigDriver();
void updateEcnsRequested(effect_handle_t effect, bool enabled);
AudioHardware* mHardware;
Mutex mLock;
int mFd;
int mFdCtl;
int mState;
int mRetryCount;
int mFormat;
uint32_t mChannels;
uint32_t mSampleRate;
size_t mBufferSize;
AudioSystem::audio_in_acoustics mAcoustics;
uint32_t mDevices;
bool mIsMicEnabled;
bool mIsBtEnabled;
int mSource;
// 20 millisecond scratch buffer
int16_t mInScratch[48000/50];
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
AudioStreamSrc mSrc;
#endif
bool mLocked; // setDriver() doesn't have to lock if true
mutable uint32_t mTotalBuffersRead;
mutable nsecs_t mStartTimeNs;
int mDriverRate;
mutable Mutex mFramesLock;
Mutex mFdLock;
bool mSleepReq;
int mEcnsRequested; // bit field indicating if AEC and/or NS are requested
};
static const uint32_t inputSamplingRates[];
bool mInit;
bool mMicMute;
bool mBluetoothNrec;
uint32_t mBluetoothId;
AudioStreamOutTegra* mOutput;
SortedVector <AudioStreamInTegra*> mInputs;
struct cpcap_audio_stream mCurOutDevice;
struct cpcap_audio_stream mCurInDevice;
friend class AudioStreamInTegra;
Mutex mLock;
int mCpcapCtlFd;
int mHwOutRate;
int mHwInRate;
float mMasterVol;
float mVoiceVol;
uint8_t mCpcapGain[AUDIO_HW_GAIN_NUM_DIRECTIONS]
[AUDIO_HW_GAIN_NUM_USECASES]
[AUDIO_HW_GAIN_NUM_PATHS];
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
AudioPostProcessor mAudioPP;
#endif
int mSpkrVolume;
int mMicVolume;
int mEcnsEnabled; // bit field indicating if AEC and/or NS are enabled
int mEcnsRequested; // bit field indicating if AEC and/or NS are requested
bool mBtScoOn;
};
// ----------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_AUDIO_HARDWARE_H