diff options
Diffstat (limited to 'services/audioflinger/AudioFlinger.h')
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 444 |
1 files changed, 418 insertions, 26 deletions
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 739ec33..5917632 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -31,10 +31,12 @@ #include <utils/Atomic.h> #include <utils/Errors.h> #include <utils/threads.h> -#include <binder/MemoryDealer.h> #include <utils/SortedVector.h> #include <utils/Vector.h> +#include <binder/BinderService.h> +#include <binder/MemoryDealer.h> + #include <hardware_legacy/AudioHardwareInterface.h> #include "AudioBufferProvider.h" @@ -42,6 +44,7 @@ namespace android { class audio_track_cblk_t; +class effect_param_cblk_t; class AudioMixer; class AudioBuffer; class AudioResampler; @@ -57,10 +60,13 @@ class AudioResampler; static const nsecs_t kStandbyTimeInNsecs = seconds(3); -class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient +class AudioFlinger : + public BinderService<AudioFlinger>, + public BnAudioFlinger { + friend class BinderService<AudioFlinger>; public: - static void instantiate(); + static char const* getServiceName() { return "media.audio_flinger"; } virtual status_t dump(int fd, const Vector<String16>& args); @@ -75,6 +81,7 @@ public: uint32_t flags, const sp<IMemory>& sharedBuffer, int output, + int *sessionId, status_t *status); virtual uint32_t sampleRate(int output) const; @@ -139,8 +146,29 @@ public: virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output); - // IBinder::DeathRecipient - virtual void binderDied(const wp<IBinder>& who); + virtual int newAudioSessionId(); + + virtual status_t loadEffectLibrary(const char *libPath, int *handle); + + virtual status_t unloadEffectLibrary(int handle); + + virtual status_t queryNumberEffects(uint32_t *numEffects); + + virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor); + + virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor); + + virtual sp<IEffect> createEffect(pid_t pid, + effect_descriptor_t *pDesc, + const sp<IEffectClient>& effectClient, + int32_t priority, + int output, + int sessionId, + status_t *status, + int *id, + int *enabled); + + virtual status_t moveEffects(int session, int srcOutput, int dstOutput); enum hardware_call_state { AUDIO_HW_IDLE = 0, @@ -170,6 +198,7 @@ public: int channelCount, int frameCount, uint32_t flags, + int *sessionId, status_t *status); virtual status_t onTransact( @@ -178,6 +207,8 @@ public: Parcel* reply, uint32_t flags); + uint32_t getMode() { return mMode; } + private: AudioFlinger(); virtual ~AudioFlinger(); @@ -205,6 +236,27 @@ private: pid_t mPid; }; + // --- Notification Client --- + class NotificationClient : public IBinder::DeathRecipient { + public: + NotificationClient(const sp<AudioFlinger>& audioFlinger, + const sp<IAudioFlingerClient>& client, + pid_t pid); + virtual ~NotificationClient(); + + sp<IAudioFlingerClient> client() { return mClient; } + + // IBinder::DeathRecipient + virtual void binderDied(const wp<IBinder>& who); + + private: + NotificationClient(const NotificationClient&); + NotificationClient& operator = (const NotificationClient&); + + sp<AudioFlinger> mAudioFlinger; + pid_t mPid; + sp<IAudioFlingerClient> mClient; + }; class TrackHandle; class RecordHandle; @@ -215,6 +267,9 @@ private: class DuplicatingThread; class Track; class RecordTrack; + class EffectModule; + class EffectHandle; + class EffectChain; class ThreadBase : public Thread { public: @@ -250,13 +305,15 @@ private: int channelCount, int frameCount, uint32_t flags, - const sp<IMemory>& sharedBuffer); + const sp<IMemory>& sharedBuffer, + int sessionId); ~TrackBase(); virtual status_t start() = 0; virtual void stop() = 0; sp<IMemory> getCblk() const; audio_track_cblk_t* cblk() const { return mCblk; } + int sessionId() { return mSessionId; } protected: friend class ThreadBase; @@ -305,6 +362,7 @@ private: int mClientTid; uint8_t mFormat; uint32_t mFlags; + int mSessionId; }; class ConfigEvent { @@ -324,7 +382,7 @@ private: virtual bool checkForNewParameters_l() = 0; virtual status_t setParameters(const String8& keyValuePairs); virtual String8 getParameters(const String8& keys) = 0; - virtual void audioConfigChanged(int event, int param = 0) = 0; + virtual void audioConfigChanged_l(int event, int param = 0) = 0; void sendConfigEvent(int event, int param = 0); void sendConfigEvent_l(int event, int param = 0); void processConfigEvents(); @@ -348,9 +406,10 @@ private: sp<AudioFlinger> mAudioFlinger; uint32_t mSampleRate; size_t mFrameCount; - int mChannelCount; + uint32_t mChannels; + uint16_t mChannelCount; + uint16_t mFrameSize; int mFormat; - uint32_t mFrameSize; Condition mParamCond; Vector<String8> mNewParameters; status_t mParamStatus; @@ -386,7 +445,8 @@ private: int format, int channelCount, int frameCount, - const sp<IMemory>& sharedBuffer); + const sp<IMemory>& sharedBuffer, + int sessionId); ~Track(); void dump(char* buffer, size_t size); @@ -405,6 +465,12 @@ private: int type() const { return mStreamType; } + status_t attachAuxEffect(int EffectId); + void setAuxBuffer(int EffectId, int32_t *buffer); + int32_t *auxBuffer() { return mAuxBuffer; } + void setMainBuffer(int16_t *buffer) { mMainBuffer = buffer; } + int16_t *mainBuffer() { return mMainBuffer; } + int auxEffectId() { return mAuxEffectId; } protected: @@ -445,6 +511,10 @@ private: bool mResetDone; int mStreamType; int mName; + int16_t *mMainBuffer; + int32_t *mAuxBuffer; + int mAuxEffectId; + bool mHasVolumeController; }; // end of Track @@ -486,7 +556,7 @@ private: DuplicatingThread* mSourceThread; }; // end of OutputTrack - PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); + PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device); virtual ~PlaybackThread(); virtual status_t dump(int fd, const Vector<String16>& args); @@ -519,6 +589,7 @@ private: int channelCount, int frameCount, const sp<IMemory>& sharedBuffer, + int sessionId, status_t *status); AudioStreamOut* getOutput() { return mOutput; } @@ -528,8 +599,49 @@ private: void restore() { if (mSuspended) mSuspended--; } bool isSuspended() { return (mSuspended != 0); } virtual String8 getParameters(const String8& keys); - virtual void audioConfigChanged(int event, int param = 0); + virtual void audioConfigChanged_l(int event, int param = 0); virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames); + int16_t *mixBuffer() { return mMixBuffer; }; + + sp<EffectHandle> createEffect_l( + const sp<AudioFlinger::Client>& client, + const sp<IEffectClient>& effectClient, + int32_t priority, + int sessionId, + effect_descriptor_t *desc, + int *enabled, + status_t *status); + void disconnectEffect(const sp< EffectModule>& effect, + const wp<EffectHandle>& handle); + + // return values for hasAudioSession (bit field) + enum effect_state { + EFFECT_SESSION = 0x1, // the audio session corresponds to at least one + // effect + TRACK_SESSION = 0x2 // the audio session corresponds to at least one + // track + }; + + uint32_t hasAudioSession(int sessionId); + sp<EffectChain> getEffectChain(int sessionId); + sp<EffectChain> getEffectChain_l(int sessionId); + status_t addEffectChain_l(const sp<EffectChain>& chain); + size_t removeEffectChain_l(const sp<EffectChain>& chain); + void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains); + void unlockEffectChains(Vector<sp <EffectChain> >& effectChains); + + sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId); + void detachAuxEffect_l(int effectId); + status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track, + int EffectId); + status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track, + int EffectId); + void setMode(uint32_t mode); + + status_t addEffect_l(const sp< EffectModule>& effect); + void removeEffect_l(const sp< EffectModule>& effect); + + uint32_t getStrategyForSession_l(int sessionId); struct stream_type_t { stream_type_t() @@ -553,6 +665,7 @@ private: virtual void deleteTrackName_l(int name) = 0; virtual uint32_t activeSleepTimeUs() = 0; virtual uint32_t idleSleepTimeUs() = 0; + virtual uint32_t suspendSleepTimeUs() = 0; private: @@ -572,8 +685,11 @@ private: void readOutputParameters(); + uint32_t device() { return mDevice; } + virtual status_t dumpInternals(int fd, const Vector<String16>& args); status_t dumpTracks(int fd, const Vector<String16>& args); + status_t dumpEffectChains(int fd, const Vector<String16>& args); SortedVector< sp<Track> > mTracks; // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread @@ -584,30 +700,33 @@ private: int mNumWrites; int mNumDelayedWrites; bool mInWrite; + Vector< sp<EffectChain> > mEffectChains; + uint32_t mDevice; }; class MixerThread : public PlaybackThread { public: - MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); + MixerThread (const sp<AudioFlinger>& audioFlinger, + AudioStreamOut* output, + int id, + uint32_t device); virtual ~MixerThread(); // Thread virtuals virtual bool threadLoop(); - void getTracks(SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks, - int streamType); - void putTracks(SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks); + void invalidateTracks(int streamType); virtual bool checkForNewParameters_l(); virtual status_t dumpInternals(int fd, const Vector<String16>& args); protected: - uint32_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove); + uint32_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, + Vector< sp<Track> > *tracksToRemove); virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); virtual uint32_t activeSleepTimeUs(); virtual uint32_t idleSleepTimeUs(); + virtual uint32_t suspendSleepTimeUs(); AudioMixer* mAudioMixer; }; @@ -615,7 +734,7 @@ private: class DirectOutputThread : public PlaybackThread { public: - DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); + DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device); ~DirectOutputThread(); // Thread virtuals @@ -628,10 +747,15 @@ private: virtual void deleteTrackName_l(int name); virtual uint32_t activeSleepTimeUs(); virtual uint32_t idleSleepTimeUs(); + virtual uint32_t suspendSleepTimeUs(); private: - float mLeftVolume; - float mRightVolume; + void applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp); + + float mLeftVolFloat; + float mRightVolFloat; + uint16_t mLeftVolShort; + uint16_t mRightVolShort; }; class DuplicatingThread : public MixerThread { @@ -661,6 +785,12 @@ private: float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } void audioConfigChanged_l(int event, int ioHandle, void *param2); + int nextUniqueId(); + status_t moveEffectChain_l(int session, + AudioFlinger::PlaybackThread *srcThread, + AudioFlinger::PlaybackThread *dstThread, + bool reRegister); + friend class AudioBuffer; class TrackHandle : public android::BnAudioTrack { @@ -674,6 +804,7 @@ private: virtual void pause(); virtual void setVolume(float left, float right); virtual sp<IMemory> getCblk() const; + virtual status_t attachAuxEffect(int effectId); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); private: @@ -685,6 +816,7 @@ private: void removeClient_l(pid_t pid); + void removeNotificationClient(pid_t pid); // record thread @@ -701,7 +833,8 @@ private: int format, int channelCount, int frameCount, - uint32_t flags); + uint32_t flags, + int sessionId); ~RecordTrack(); virtual status_t start(); @@ -744,7 +877,7 @@ private: virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); virtual bool checkForNewParameters_l(); virtual String8 getParameters(const String8& keys); - virtual void audioConfigChanged(int event, int param = 0); + virtual void audioConfigChanged_l(int event, int param = 0); void readInputParameters(); virtual unsigned int getInputFramesLost(); @@ -776,6 +909,260 @@ private: sp<RecordThread::RecordTrack> mRecordTrack; }; + //--- Audio Effect Management + + // EffectModule and EffectChain classes both have their own mutex to protect + // state changes or resource modifications. Always respect the following order + // if multiple mutexes must be acquired to avoid cross deadlock: + // AudioFlinger -> ThreadBase -> EffectChain -> EffectModule + + // The EffectModule class is a wrapper object controlling the effect engine implementation + // in the effect library. It prevents concurrent calls to process() and command() functions + // from different client threads. It keeps a list of EffectHandle objects corresponding + // to all client applications using this effect and notifies applications of effect state, + // control or parameter changes. It manages the activation state machine to send appropriate + // reset, enable, disable commands to effect engine and provide volume + // ramping when effects are activated/deactivated. + // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by + // the attached track(s) to accumulate their auxiliary channel. + class EffectModule: public RefBase { + public: + EffectModule(const wp<ThreadBase>& wThread, + const wp<AudioFlinger::EffectChain>& chain, + effect_descriptor_t *desc, + int id, + int sessionId); + ~EffectModule(); + + enum effect_state { + IDLE, + RESTART, + STARTING, + ACTIVE, + STOPPING, + STOPPED + }; + + int id() { return mId; } + void process(); + void updateState(); + status_t command(uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t *replySize, + void *pReplyData); + + void reset_l(); + status_t configure(); + status_t init(); + uint32_t state() { + return mState; + } + uint32_t status() { + return mStatus; + } + int sessionId() { + return mSessionId; + } + status_t setEnabled(bool enabled); + bool isEnabled(); + bool isProcessEnabled(); + + void setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; } + int16_t *inBuffer() { return mConfig.inputCfg.buffer.s16; } + void setOutBuffer(int16_t *buffer) { mConfig.outputCfg.buffer.s16 = buffer; } + int16_t *outBuffer() { return mConfig.outputCfg.buffer.s16; } + void setChain(const wp<EffectChain>& chain) { mChain = chain; } + void setThread(const wp<ThreadBase>& thread) { mThread = thread; } + + status_t addHandle(sp<EffectHandle>& handle); + void disconnect(const wp<EffectHandle>& handle); + size_t removeHandle (const wp<EffectHandle>& handle); + + effect_descriptor_t& desc() { return mDescriptor; } + wp<EffectChain>& chain() { return mChain; } + + status_t setDevice(uint32_t device); + status_t setVolume(uint32_t *left, uint32_t *right, bool controller); + status_t setMode(uint32_t mode); + + status_t dump(int fd, const Vector<String16>& args); + + protected: + + // Maximum time allocated to effect engines to complete the turn off sequence + static const uint32_t MAX_DISABLE_TIME_MS = 10000; + + EffectModule(const EffectModule&); + EffectModule& operator = (const EffectModule&); + + status_t start_l(); + status_t stop_l(); + + // update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified + static const uint32_t sDeviceConvTable[]; + static uint32_t deviceAudioSystemToEffectApi(uint32_t device); + + // update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified + static const uint32_t sModeConvTable[]; + static int modeAudioSystemToEffectApi(uint32_t mode); + + Mutex mLock; // mutex for process, commands and handles list protection + wp<ThreadBase> mThread; // parent thread + wp<EffectChain> mChain; // parent effect chain + int mId; // this instance unique ID + int mSessionId; // audio session ID + effect_descriptor_t mDescriptor;// effect descriptor received from effect engine + effect_config_t mConfig; // input and output audio configuration + effect_interface_t mEffectInterface; // Effect module C API + status_t mStatus; // initialization status + uint32_t mState; // current activation state (effect_state) + Vector< wp<EffectHandle> > mHandles; // list of client handles + uint32_t mMaxDisableWaitCnt; // maximum grace period before forcing an effect off after + // sending disable command. + uint32_t mDisableWaitCnt; // current process() calls count during disable period. + }; + + // The EffectHandle class implements the IEffect interface. It provides resources + // to receive parameter updates, keeps track of effect control + // ownership and state and has a pointer to the EffectModule object it is controlling. + // There is one EffectHandle object for each application controlling (or using) + // an effect module. + // The EffectHandle is obtained by calling AudioFlinger::createEffect(). + class EffectHandle: public android::BnEffect { + public: + + EffectHandle(const sp<EffectModule>& effect, + const sp<AudioFlinger::Client>& client, + const sp<IEffectClient>& effectClient, + int32_t priority); + virtual ~EffectHandle(); + + // IEffect + virtual status_t enable(); + virtual status_t disable(); + virtual status_t command(uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t *replySize, + void *pReplyData); + virtual void disconnect(); + virtual sp<IMemory> getCblk() const; + virtual status_t onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags); + + + // Give or take control of effect module + void setControl(bool hasControl, bool signal); + void commandExecuted(uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t replySize, + void *pReplyData); + void setEnabled(bool enabled); + + // Getters + int id() { return mEffect->id(); } + int priority() { return mPriority; } + bool hasControl() { return mHasControl; } + sp<EffectModule> effect() { return mEffect; } + + void dump(char* buffer, size_t size); + + protected: + + EffectHandle(const EffectHandle&); + EffectHandle& operator =(const EffectHandle&); + + sp<EffectModule> mEffect; // pointer to controlled EffectModule + sp<IEffectClient> mEffectClient; // callback interface for client notifications + sp<Client> mClient; // client for shared memory allocation + sp<IMemory> mCblkMemory; // shared memory for control block + effect_param_cblk_t* mCblk; // control block for deferred parameter setting via shared memory + uint8_t* mBuffer; // pointer to parameter area in shared memory + int mPriority; // client application priority to control the effect + bool mHasControl; // true if this handle is controlling the effect + }; + + // the EffectChain class represents a group of effects associated to one audio session. + // There can be any number of EffectChain objects per output mixer thread (PlaybackThread). + // The EffecChain with session ID 0 contains global effects applied to the output mix. + // Effects in this chain can be insert or auxiliary. Effects in other chains (attached to tracks) + // are insert only. The EffectChain maintains an ordered list of effect module, the order corresponding + // in the effect process order. When attached to a track (session ID != 0), it also provide it's own + // input buffer used by the track as accumulation buffer. + class EffectChain: public RefBase { + public: + EffectChain(const wp<ThreadBase>& wThread, int sessionId); + ~EffectChain(); + + void process_l(); + + void lock() { + mLock.lock(); + } + void unlock() { + mLock.unlock(); + } + + status_t addEffect_l(const sp<EffectModule>& handle); + size_t removeEffect_l(const sp<EffectModule>& handle); + + int sessionId() { + return mSessionId; + } + + sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor); + sp<EffectModule> getEffectFromId_l(int id); + bool setVolume_l(uint32_t *left, uint32_t *right); + void setDevice_l(uint32_t device); + void setMode_l(uint32_t mode); + + void setInBuffer(int16_t *buffer, bool ownsBuffer = false) { + mInBuffer = buffer; + mOwnInBuffer = ownsBuffer; + } + int16_t *inBuffer() { + return mInBuffer; + } + void setOutBuffer(int16_t *buffer) { + mOutBuffer = buffer; + } + int16_t *outBuffer() { + return mOutBuffer; + } + + void startTrack() {mActiveTrackCnt++;} + void stopTrack() {mActiveTrackCnt--;} + int activeTracks() { return mActiveTrackCnt;} + + uint32_t strategy() { return mStrategy; } + void setStrategy(uint32_t strategy) + { mStrategy = strategy; } + + status_t dump(int fd, const Vector<String16>& args); + + protected: + + EffectChain(const EffectChain&); + EffectChain& operator =(const EffectChain&); + + wp<ThreadBase> mThread; // parent mixer thread + Mutex mLock; // mutex protecting effect list + Vector<sp<EffectModule> > mEffects; // list of effect modules + int mSessionId; // audio session ID + int16_t *mInBuffer; // chain input buffer + int16_t *mOutBuffer; // chain output buffer + int mActiveTrackCnt; // number of active tracks connected + bool mOwnInBuffer; // true if the chain owns its input buffer + int mVolumeCtrlIdx; // index of insert effect having control over volume + uint32_t mLeftVolume; // previous volume on left channel + uint32_t mRightVolume; // previous volume on right channel + uint32_t mNewLeftVolume; // new volume on left channel + uint32_t mNewRightVolume; // new volume on right channel + uint32_t mStrategy; // strategy for this effect chain + }; + friend class RecordThread; friend class PlaybackThread; @@ -796,8 +1183,13 @@ private: DefaultKeyedVector< int, sp<RecordThread> > mRecordThreads; - SortedVector< sp<IBinder> > mNotificationClients; - int mNextThreadId; + DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients; + volatile int32_t mNextUniqueId; +#ifdef LVMX + int mLifeVibesClientPid; +#endif + uint32_t mMode; + }; // ---------------------------------------------------------------------------- |