C++程序  |  594行  |  17.88 KB

/* AudioHardwareALSA.h
 **
 ** Copyright 2008-2010, Wind River Systems
 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
 **
 ** 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_ALSA_H
#define ANDROID_AUDIO_HARDWARE_ALSA_H

#define QCOM_CSDCLIENT_ENABLED 1

#include <utils/List.h>
#include <hardware_legacy/AudioHardwareBase.h>

#include <hardware_legacy/AudioHardwareInterface.h>
#include <hardware_legacy/AudioSystemLegacy.h>
#include <system/audio.h>
#include <hardware/audio.h>
#include <utils/threads.h>
#include <dlfcn.h>

#ifdef QCOM_USBAUDIO_ENABLED
#include <AudioUsbALSA.h>
#endif

extern "C" {
   #include <sound/asound.h>
   #include "alsa_audio.h"
   #include "msm8960_use_cases.h"
}

#include <hardware/hardware.h>

namespace android_audio_legacy
{
using android::List;
using android::Mutex;
class AudioHardwareALSA;

/**
 * The id of ALSA module
 */
#define ALSA_HARDWARE_MODULE_ID "alsa"
#define ALSA_HARDWARE_NAME      "alsa"

#define DEFAULT_SAMPLING_RATE 48000
#define DEFAULT_CHANNEL_MODE  2
#define VOICE_SAMPLING_RATE   8000
#define VOICE_CHANNEL_MODE    1
#define PLAYBACK_LATENCY      170000
#define RECORD_LATENCY        96000
#define VOICE_LATENCY         85333
#define DEFAULT_BUFFER_SIZE   4096
//4032 = 336(kernel buffer size) * 2(bytes pcm_16) * 6(number of channels)
#define DEFAULT_MULTI_CHANNEL_BUF_SIZE    4032
#define DEFAULT_VOICE_BUFFER_SIZE   2048
#define PLAYBACK_LOW_LATENCY_BUFFER_SIZE   1024
#define PLAYBACK_LOW_LATENCY  22000
#define PLAYBACK_LOW_LATENCY_MEASURED  42000
#define DEFAULT_IN_BUFFER_SIZE 320
#define MIN_CAPTURE_BUFFER_SIZE_PER_CH   320
#define MAX_CAPTURE_BUFFER_SIZE_PER_CH   2048
#define FM_BUFFER_SIZE        1024

#define VOIP_SAMPLING_RATE_8K 8000
#define VOIP_SAMPLING_RATE_16K 16000
#define VOIP_DEFAULT_CHANNEL_MODE  1
#define VOIP_BUFFER_SIZE_8K    320
#define VOIP_BUFFER_SIZE_16K   640
#define VOIP_BUFFER_MAX_SIZE   VOIP_BUFFER_SIZE_16K
#define VOIP_PLAYBACK_LATENCY      6400
#define VOIP_RECORD_LATENCY        6400

#define MODE_IS127              0x2
#define MODE_4GV_NB             0x3
#define MODE_4GV_WB             0x4
#define MODE_AMR                0x5
#define MODE_AMR_WB             0xD
#define MODE_PCM                0xC

#define DUALMIC_KEY         "dualmic_enabled"
#define FLUENCE_KEY         "fluence"
#define ANC_KEY             "anc_enabled"
#define TTY_MODE_KEY        "tty_mode"
#define BT_SAMPLERATE_KEY   "bt_samplerate"
#define BTHEADSET_VGS       "bt_headset_vgs"
#define WIDEVOICE_KEY       "wide_voice_enable"
#define VOIPRATE_KEY        "voip_rate"
#define FENS_KEY            "fens_enable"
#define ST_KEY              "st_enable"
#define INCALLMUSIC_KEY     "incall_music_enabled"

#define ANC_FLAG        0x00000001
#define DMIC_FLAG       0x00000002
#define QMIC_FLAG       0x00000004
#ifdef QCOM_SSR_ENABLED
#define SSRQMIC_FLAG    0x00000008
#endif

#define TTY_OFF         0x00000010
#define TTY_FULL        0x00000020
#define TTY_VCO         0x00000040
#define TTY_HCO         0x00000080
#define TTY_CLEAR       0xFFFFFF0F

#define LPA_SESSION_ID 1
#define TUNNEL_SESSION_ID 2
#ifdef QCOM_USBAUDIO_ENABLED
static int USBPLAYBACKBIT_MUSIC = (1 << 0);
static int USBPLAYBACKBIT_VOICECALL = (1 << 1);
static int USBPLAYBACKBIT_VOIPCALL = (1 << 2);
static int USBPLAYBACKBIT_FM = (1 << 3);
static int USBPLAYBACKBIT_LPA = (1 << 4);

static int USBRECBIT_REC = (1 << 0);
static int USBRECBIT_VOICECALL = (1 << 1);
static int USBRECBIT_VOIPCALL = (1 << 2);
static int USBRECBIT_FM = (1 << 3);
#endif

#define DEVICE_SPEAKER_HEADSET "Speaker Headset"
#define DEVICE_HEADSET "Headset"
#define DEVICE_HEADPHONES "Headphones"

#ifdef QCOM_SSR_ENABLED
#define COEFF_ARRAY_SIZE          4
#define FILT_SIZE                 ((512+1)* 6)    /* # ((FFT bins)/2+1)*numOutputs */
#define SSR_FRAME_SIZE            512
#define SSR_INPUT_FRAME_SIZE      (SSR_FRAME_SIZE * 4)
#define SSR_OUTPUT_FRAME_SIZE     (SSR_FRAME_SIZE * 6)
#endif

#define MODE_CALL_KEY  "CALL_KEY"

struct alsa_device_t;
static uint32_t FLUENCE_MODE_ENDFIRE   = 0;
static uint32_t FLUENCE_MODE_BROADSIDE = 1;

enum {
    INCALL_REC_MONO,
    INCALL_REC_STEREO,
};

enum audio_call_mode {
    CS_INACTIVE   = 0x0,
    CS_ACTIVE     = 0x1,
    CS_HOLD       = 0x2,
    IMS_INACTIVE  = 0x0,
    IMS_ACTIVE    = 0x10,
    IMS_HOLD      = 0x20
};


struct alsa_handle_t {
    alsa_device_t *     module;
    uint32_t            devices;
    char                useCase[MAX_STR_LEN];
    struct pcm *        handle;
    snd_pcm_format_t    format;
    uint32_t            channels;
    audio_channel_mask_t channelMask;
    uint32_t            sampleRate;
    unsigned int        latency;         // Delay in usec
    unsigned int        bufferSize;      // Size of sample buffer
    unsigned int        periodSize;
    bool                isDeepbufferOutput;
    struct pcm *        rxHandle;
    snd_use_case_mgr_t  *ucMgr;
};

typedef List < alsa_handle_t > ALSAHandleList;

struct use_case_t {
    char                useCase[MAX_STR_LEN];
};

typedef List < use_case_t > ALSAUseCaseList;

struct alsa_device_t {
    hw_device_t common;

    status_t (*init)(alsa_device_t *, ALSAHandleList &);
    status_t (*open)(alsa_handle_t *);
    status_t (*close)(alsa_handle_t *);
    status_t (*standby)(alsa_handle_t *);
    status_t (*route)(alsa_handle_t *, uint32_t, int);
    status_t (*startVoiceCall)(alsa_handle_t *);
    status_t (*startVoipCall)(alsa_handle_t *);
    status_t (*startFm)(alsa_handle_t *);
    void     (*setVoiceVolume)(int);
    void     (*setVoipVolume)(int);
    void     (*setMicMute)(int);
    void     (*setVoipMicMute)(int);
    void     (*setVoipConfig)(int, int);
    status_t (*setFmVolume)(int);
    void     (*setBtscoRate)(int);
    status_t (*setLpaVolume)(int);
    void     (*enableWideVoice)(bool);
    void     (*enableFENS)(bool);
    void     (*setFlags)(uint32_t);
    status_t (*setCompressedVolume)(int);
    void     (*enableSlowTalk)(bool);
    void     (*setVocRecMode)(uint8_t);
    void     (*setVoLTEMicMute)(int);
    void     (*setVoLTEVolume)(int);
#ifdef SEPERATED_AUDIO_INPUT
    void     (*setInput)(int);
#endif
#ifdef QCOM_CSDCLIENT_ENABLED
    void     (*setCsdHandle)(void*);
#endif
};

// ----------------------------------------------------------------------------

class ALSAMixer
{
public:
    ALSAMixer();
    virtual                ~ALSAMixer();

    bool                    isValid() { return 1;}
    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);

};

class ALSAControl
{
public:
    ALSAControl(const char *device = "/dev/snd/controlC0");
    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                set(const char *name, const char *);
    status_t                setext(const char *name, int count, char **setValues);

private:
    struct mixer*             mHandle;
};

class ALSAStreamOps
{
public:
    ALSAStreamOps(AudioHardwareALSA *parent, alsa_handle_t *handle);
    virtual            ~ALSAStreamOps();

    status_t            set(int *format, uint32_t *channels, uint32_t *rate, uint32_t device);

    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;

    AudioHardwareALSA *     mParent;
    alsa_handle_t *         mHandle;
    uint32_t                mDevices;
};

// ----------------------------------------------------------------------------

class AudioStreamOutALSA : public AudioStreamOut, public ALSAStreamOps
{
public:
    AudioStreamOutALSA(AudioHardwareALSA *parent, alsa_handle_t *handle);
    virtual            ~AudioStreamOutALSA();

    virtual uint32_t    sampleRate() const
    {
        return ALSAStreamOps::sampleRate();
    }

    virtual size_t      bufferSize() const
    {
        return ALSAStreamOps::bufferSize();
    }

    virtual uint32_t    channels() const;

    virtual int         format() const
    {
        return ALSAStreamOps::format();
    }

    virtual uint32_t    latency() const;

    virtual ssize_t     write(const void *buffer, size_t bytes);
    virtual status_t    dump(int fd, const Vector<String16>& args);

    status_t            setVolume(float left, float right);

    virtual status_t    standby();

    virtual status_t    setParameters(const String8& keyValuePairs) {
        return ALSAStreamOps::setParameters(keyValuePairs);
    }

    virtual String8     getParameters(const String8& keys) {
        return ALSAStreamOps::getParameters(keys);
    }

    // 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);

    status_t            open(int mode);
    status_t            close();

private:
    uint32_t            mFrameCount;

protected:
    AudioHardwareALSA *     mParent;
};

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
    {
        return ALSAStreamOps::channels();
    }

    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 status_t    setParameters(const String8& keyValuePairs)
    {
        return ALSAStreamOps::setParameters(keyValuePairs);
    }

    virtual String8     getParameters(const String8& keys)
    {
        return ALSAStreamOps::getParameters(keys);
    }

    // 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 status_t addAudioEffect(effect_handle_t effect)
    {
        return BAD_VALUE;
    }
   
    virtual status_t removeAudioEffect(effect_handle_t effect)
    {
        return BAD_VALUE;
    }
    status_t            setAcousticParams(void* params);

    status_t            open(int mode);
    status_t            close();
#ifdef QCOM_SSR_ENABLED
    // Helper function to initialize the Surround Sound library.
    status_t initSurroundSoundLibrary(unsigned long buffersize);
#endif

private:
    void                resetFramesLost();

#ifdef QCOM_CSDCLIENT_ENABLED
    int                 start_csd_record(int);
    int                 stop_csd_record(void);
#endif

    unsigned int        mFramesLost;
    AudioSystem::audio_in_acoustics mAcoustics;

#ifdef QCOM_SSR_ENABLED
    // Function to read coefficients from files.
    status_t            readCoeffsFromFile();

    FILE                *mFp_4ch;
    FILE                *mFp_6ch;
    int16_t             **mRealCoeffs;
    int16_t             **mImagCoeffs;
    void                *mSurroundObj;

    int16_t             *mSurroundInputBuffer;
    int16_t             *mSurroundOutputBuffer;
    int                 mSurroundInputBufferIdx;
    int                 mSurroundOutputBufferIdx;
#endif

protected:
    AudioHardwareALSA *     mParent;
};

class AudioHardwareALSA : public AudioHardwareBase
{
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();

    /** 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);
#ifdef QCOM_FM_ENABLED
    virtual status_t    setFmVolume(float volume);
#endif
    /**
     * 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);

#ifdef QCOM_TUNNEL_LPA_ENABLED
    /** This method creates and opens the audio hardware output
      *  session for LPA */
    virtual AudioStreamOut* openOutputSession(
            uint32_t devices,
            int *format,
            status_t *status,
            int sessionId,
            uint32_t samplingRate=0,
            uint32_t channels=0);
    virtual void closeOutputSession(AudioStreamOut* out);
#endif

    /** 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()
    {
        return mMode;
    }

protected:
    virtual status_t    dump(int fd, const Vector<String16>& args);
    virtual uint32_t    getVoipMode(int format);
    void                doRouting(int device);
#ifdef QCOM_FM_ENABLED
    void                handleFm(int device);
#endif
#ifdef QCOM_USBAUDIO_ENABLED
    void                closeUSBPlayback();
    void                closeUSBRecording();
    void                closeUsbRecordingIfNothingActive();
    void                closeUsbPlaybackIfNothingActive();
    void                startUsbPlaybackIfNotStarted();
    void                startUsbRecordingIfNotStarted();
#endif

    void                disableVoiceCall(char* verb, char* modifier, int mode, int device);
    void                enableVoiceCall(char* verb, char* modifier, int mode, int device);
    bool                routeVoiceCall(int device, int	newMode);
    bool                routeVoLTECall(int device, int newMode);
    friend class AudioStreamOutALSA;
    friend class AudioStreamInALSA;
    friend class ALSAStreamOps;

    alsa_device_t *     mALSADevice;

    ALSAHandleList      mDeviceList;

#ifdef QCOM_USBAUDIO_ENABLED
    AudioUsbALSA        *mAudioUsbALSA;
#endif

    Mutex                   mLock;

    snd_use_case_mgr_t *mUcMgr;

    uint32_t            mCurDevice;
    /* The flag holds all the audio related device settings from
     * Settings and Qualcomm Settings applications */
    uint32_t            mDevSettingsFlag;
    uint32_t            mVoipStreamCount;
    uint32_t            mVoipBitRate;
    uint32_t            mIncallMode;

    bool                mMicMute;
    int mCSCallActive;
    int mVolteCallActive;
    int mCallState;
    int mIsFmActive;
    bool mBluetoothVGS;
    bool mFusion3Platform;
#ifdef QCOM_USBAUDIO_ENABLED
    int musbPlaybackState;
    int musbRecordingState;
#endif
    void *mAcdbHandle;
    void *mCsdHandle;
};

// ----------------------------------------------------------------------------

};        // namespace android_audio_legacy
#endif    // ANDROID_AUDIO_HARDWARE_ALSA_H