summaryrefslogtreecommitdiffstats
path: root/libs/audioflinger/AudioFlinger.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/audioflinger/AudioFlinger.h')
-rw-r--r--libs/audioflinger/AudioFlinger.h637
1 files changed, 637 insertions, 0 deletions
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
new file mode 100644
index 0000000..77f064b
--- /dev/null
+++ b/libs/audioflinger/AudioFlinger.h
@@ -0,0 +1,637 @@
+/* //device/include/server/AudioFlinger/AudioFlinger.h
+**
+** Copyright 2007, 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_FLINGER_H
+#define ANDROID_AUDIO_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IAudioFlingerClient.h>
+#include <media/IAudioTrack.h>
+#include <media/IAudioRecord.h>
+#include <media/AudioTrack.h>
+
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <utils/MemoryDealer.h>
+#include <utils/KeyedVector.h>
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
+
+#include <hardware_legacy/AudioHardwareInterface.h>
+
+#include "AudioBufferProvider.h"
+
+namespace android {
+
+class audio_track_cblk_t;
+class AudioMixer;
+class AudioBuffer;
+
+
+// ----------------------------------------------------------------------------
+
+#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+
+
+// ----------------------------------------------------------------------------
+
+static const nsecs_t kStandbyTimeInNsecs = seconds(3);
+
+class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient
+{
+public:
+ static void instantiate();
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ // IAudioFlinger interface
+ virtual sp<IAudioTrack> createTrack(
+ pid_t pid,
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount,
+ uint32_t flags,
+ const sp<IMemory>& sharedBuffer,
+ status_t *status);
+
+ virtual uint32_t sampleRate(int output) const;
+ virtual int channelCount(int output) const;
+ virtual int format(int output) const;
+ virtual size_t frameCount(int output) const;
+ virtual uint32_t latency(int output) const;
+
+ virtual status_t setMasterVolume(float value);
+ virtual status_t setMasterMute(bool muted);
+
+ virtual float masterVolume() const;
+ virtual bool masterMute() const;
+
+ virtual status_t setStreamVolume(int stream, float value);
+ virtual status_t setStreamMute(int stream, bool muted);
+
+ virtual float streamVolume(int stream) const;
+ virtual bool streamMute(int stream) const;
+
+ virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask);
+ virtual uint32_t getRouting(int mode) const;
+
+ virtual status_t setMode(int mode);
+ virtual int getMode() const;
+
+ virtual status_t setMicMute(bool state);
+ virtual bool getMicMute() const;
+
+ virtual bool isMusicActive() const;
+
+ virtual bool isA2dpEnabled() const;
+
+ virtual status_t setParameter(const char* key, const char* value);
+
+ virtual void registerClient(const sp<IAudioFlingerClient>& client);
+
+ virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
+
+ virtual void wakeUp();
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ enum hardware_call_state {
+ AUDIO_HW_IDLE = 0,
+ AUDIO_HW_INIT,
+ AUDIO_HW_OUTPUT_OPEN,
+ AUDIO_HW_OUTPUT_CLOSE,
+ AUDIO_HW_INPUT_OPEN,
+ AUDIO_HW_INPUT_CLOSE,
+ AUDIO_HW_STANDBY,
+ AUDIO_HW_SET_MASTER_VOLUME,
+ AUDIO_HW_GET_ROUTING,
+ AUDIO_HW_SET_ROUTING,
+ AUDIO_HW_GET_MODE,
+ AUDIO_HW_SET_MODE,
+ AUDIO_HW_GET_MIC_MUTE,
+ AUDIO_HW_SET_MIC_MUTE,
+ AUDIO_SET_VOICE_VOLUME,
+ AUDIO_SET_PARAMETER,
+ };
+
+ // record interface
+ virtual sp<IAudioRecord> openRecord(
+ pid_t pid,
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount,
+ uint32_t flags,
+ status_t *status);
+
+ virtual status_t onTransact(
+ uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags);
+
+private:
+ AudioFlinger();
+ virtual ~AudioFlinger();
+
+ void setOutput(int outputType);
+ void doSetOutput(int outputType);
+
+#ifdef WITH_A2DP
+ void setA2dpEnabled(bool enable);
+#endif
+ static bool streamForcedToSpeaker(int streamType);
+
+ // Management of forced route to speaker for certain track types.
+ enum force_speaker_command {
+ ACTIVE_TRACK_ADDED = 0,
+ ACTIVE_TRACK_REMOVED,
+ CHECK_ROUTE_RESTORE_TIME,
+ FORCE_ROUTE_RESTORE
+ };
+ void handleForcedSpeakerRoute(int command);
+
+ // Internal dump utilites.
+ status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
+ status_t dumpClients(int fd, const Vector<String16>& args);
+ status_t dumpInternals(int fd, const Vector<String16>& args);
+
+ // --- Client ---
+ class Client : public RefBase {
+ public:
+ Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
+ virtual ~Client();
+ const sp<MemoryDealer>& heap() const;
+ pid_t pid() const { return mPid; }
+ private:
+ Client(const Client&);
+ Client& operator = (const Client&);
+ sp<AudioFlinger> mAudioFlinger;
+ sp<MemoryDealer> mMemoryDealer;
+ pid_t mPid;
+ };
+
+
+ class TrackHandle;
+ class RecordHandle;
+ class AudioRecordThread;
+
+
+ // --- MixerThread ---
+ class MixerThread : public Thread {
+ public:
+
+ // --- Track ---
+
+ // base for record and playback
+ class TrackBase : public AudioBufferProvider, public RefBase {
+
+ public:
+ enum track_state {
+ IDLE,
+ TERMINATED,
+ STOPPED,
+ RESUMING,
+ ACTIVE,
+ PAUSING,
+ PAUSED
+ };
+
+ enum track_flags {
+ STEPSERVER_FAILED = 0x01, // StepServer could not acquire cblk->lock mutex
+ SYSTEM_FLAGS_MASK = 0x0000ffffUL,
+ // The upper 16 bits are used for track-specific flags.
+ };
+
+ TrackBase(const sp<MixerThread>& mixerThread,
+ const sp<Client>& client,
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount,
+ uint32_t flags,
+ const sp<IMemory>& sharedBuffer);
+ ~TrackBase();
+
+ virtual status_t start() = 0;
+ virtual void stop() = 0;
+ sp<IMemory> getCblk() const;
+
+ protected:
+ friend class MixerThread;
+ friend class RecordHandle;
+ friend class AudioRecordThread;
+
+ TrackBase(const TrackBase&);
+ TrackBase& operator = (const TrackBase&);
+
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
+ virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+
+ audio_track_cblk_t* cblk() const {
+ return mCblk;
+ }
+
+ int type() const {
+ return mStreamType;
+ }
+
+ int format() const {
+ return mFormat;
+ }
+
+ int channelCount() const ;
+
+ int sampleRate() const;
+
+ void* getBuffer(uint32_t offset, uint32_t frames) const;
+
+ int name() const {
+ return mName;
+ }
+
+ bool isStopped() const {
+ return mState == STOPPED;
+ }
+
+ bool isTerminated() const {
+ return mState == TERMINATED;
+ }
+
+ bool step();
+ void reset();
+
+ sp<MixerThread> mMixerThread;
+ sp<Client> mClient;
+ sp<IMemory> mCblkMemory;
+ audio_track_cblk_t* mCblk;
+ int mStreamType;
+ void* mBuffer;
+ void* mBufferEnd;
+ uint32_t mFrameCount;
+ int mName;
+ // we don't really need a lock for these
+ int mState;
+ int mClientTid;
+ uint8_t mFormat;
+ uint32_t mFlags;
+ };
+
+ // playback track
+ class Track : public TrackBase {
+ public:
+ Track( const sp<MixerThread>& mixerThread,
+ const sp<Client>& client,
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer);
+ ~Track();
+
+ void dump(char* buffer, size_t size);
+ virtual status_t start();
+ virtual void stop();
+ void pause();
+
+ void flush();
+ void destroy();
+ void mute(bool);
+ void setVolume(float left, float right);
+
+ protected:
+ friend class MixerThread;
+ friend class AudioFlinger;
+ friend class AudioFlinger::TrackHandle;
+
+ Track(const Track&);
+ Track& operator = (const Track&);
+
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+
+ bool isMuted() const {
+ return (mMute || mMixerThread->mStreamTypes[mStreamType].mute);
+ }
+
+ bool isPausing() const {
+ return mState == PAUSING;
+ }
+
+ bool isPaused() const {
+ return mState == PAUSED;
+ }
+
+ bool isReady() const;
+
+ void setPaused() { mState = PAUSED; }
+ void reset();
+
+ // we don't really need a lock for these
+ float mVolume[2];
+ volatile bool mMute;
+ // FILLED state is used for suppressing volume ramp at begin of playing
+ enum {FS_FILLING, FS_FILLED, FS_ACTIVE};
+ mutable uint8_t mFillingUpStatus;
+ int8_t mRetryCount;
+ sp<IMemory> mSharedBuffer;
+ bool mResetDone;
+ }; // end of Track
+
+ // record track
+ class RecordTrack : public TrackBase {
+ public:
+ RecordTrack(const sp<MixerThread>& mixerThread,
+ const sp<Client>& client,
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount,
+ uint32_t flags);
+ ~RecordTrack();
+
+ virtual status_t start();
+ virtual void stop();
+
+ bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
+ bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
+
+ private:
+ friend class AudioFlinger;
+ friend class AudioFlinger::RecordHandle;
+ friend class AudioFlinger::AudioRecordThread;
+ friend class MixerThread;
+
+ RecordTrack(const Track&);
+ RecordTrack& operator = (const Track&);
+
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+
+ bool mOverflow;
+ };
+
+ // playback track
+ class OutputTrack : public Track {
+ public:
+
+ class Buffer: public AudioBufferProvider::Buffer {
+ public:
+ int16_t *mBuffer;
+ };
+
+ OutputTrack( const sp<MixerThread>& mixerThread,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount);
+ ~OutputTrack();
+
+ virtual status_t start();
+ virtual void stop();
+ void write(int16_t* data, uint32_t frames);
+ bool bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; }
+
+ private:
+
+ status_t obtainBuffer(AudioBufferProvider::Buffer* buffer);
+ void clearBufferQueue();
+
+ sp<MixerThread> mOutputMixerThread;
+ Vector < Buffer* > mBufferQueue;
+ AudioBufferProvider::Buffer mOutBuffer;
+ uint32_t mFramesWritten;
+
+ }; // end of OutputTrack
+
+ MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType);
+ virtual ~MixerThread();
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ // Thread virtuals
+ virtual bool threadLoop();
+ virtual status_t readyToRun();
+ virtual void onFirstRef();
+
+ virtual uint32_t sampleRate() const;
+ virtual int channelCount() const;
+ virtual int format() const;
+ virtual size_t frameCount() const;
+ virtual uint32_t latency() const;
+
+ virtual status_t setMasterVolume(float value);
+ virtual status_t setMasterMute(bool muted);
+
+ virtual float masterVolume() const;
+ virtual bool masterMute() const;
+
+ virtual status_t setStreamVolume(int stream, float value);
+ virtual status_t setStreamMute(int stream, bool muted);
+
+ virtual float streamVolume(int stream) const;
+ virtual bool streamMute(int stream) const;
+
+ bool isMusicActive() const;
+
+
+ sp<Track> createTrack(
+ const sp<AudioFlinger::Client>& client,
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ status_t *status);
+
+ void wakeUp() { mWaitWorkCV.broadcast(); }
+
+ void getTracks(SortedVector < sp<Track> >& tracks,
+ SortedVector < wp<Track> >& activeTracks);
+ void putTracks(SortedVector < sp<Track> >& tracks,
+ SortedVector < wp<Track> >& activeTracks);
+ void setOuputTrack(OutputTrack *track) { mOutputTrack = track; }
+
+ struct stream_type_t {
+ stream_type_t()
+ : volume(1.0f),
+ mute(false)
+ {
+ }
+ float volume;
+ bool mute;
+ };
+
+ private:
+
+
+ friend class AudioFlinger;
+ friend class Track;
+ friend class TrackBase;
+ friend class RecordTrack;
+
+ MixerThread(const Client&);
+ MixerThread& operator = (const MixerThread&);
+
+ status_t addTrack(const sp<Track>& track);
+ void removeTrack(wp<Track> track, int name);
+ void remove_track_l(wp<Track> track, int name);
+ void destroyTrack(const sp<Track>& track);
+ int getTrackName();
+ void deleteTrackName(int name);
+ void addActiveTrack(const wp<Track>& t);
+ void removeActiveTrack(const wp<Track>& t);
+ size_t getOutputFrameCount();
+
+ status_t dumpInternals(int fd, const Vector<String16>& args);
+ status_t dumpTracks(int fd, const Vector<String16>& args);
+
+ sp<AudioFlinger> mAudioFlinger;
+ mutable Mutex mLock;
+ mutable Condition mWaitWorkCV;
+ SortedVector< wp<Track> > mActiveTracks;
+ SortedVector< sp<Track> > mTracks;
+ stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
+ AudioMixer* mAudioMixer;
+ AudioStreamOut* mOutput;
+ int mOutputType;
+ uint32_t mSampleRate;
+ size_t mFrameCount;
+ int mChannelCount;
+ int mFormat;
+ int16_t* mMixBuffer;
+ float mMasterVolume;
+ bool mMasterMute;
+ nsecs_t mLastWriteTime;
+ int mNumWrites;
+ int mNumDelayedWrites;
+ bool mStandby;
+ bool mInWrite;
+ sp <OutputTrack> mOutputTrack;
+ };
+
+
+ friend class AudioBuffer;
+
+ class TrackHandle : public android::BnAudioTrack {
+ public:
+ TrackHandle(const sp<MixerThread::Track>& track);
+ virtual ~TrackHandle();
+ virtual status_t start();
+ virtual void stop();
+ virtual void flush();
+ virtual void mute(bool);
+ virtual void pause();
+ virtual void setVolume(float left, float right);
+ virtual sp<IMemory> getCblk() const;
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+ private:
+ sp<MixerThread::Track> mTrack;
+ };
+
+ friend class Client;
+ friend class MixerThread::Track;
+
+
+ void removeClient(pid_t pid);
+
+
+
+ class RecordHandle : public android::BnAudioRecord {
+ public:
+ RecordHandle(const sp<MixerThread::RecordTrack>& recordTrack);
+ virtual ~RecordHandle();
+ virtual status_t start();
+ virtual void stop();
+ virtual sp<IMemory> getCblk() const;
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+ private:
+ sp<MixerThread::RecordTrack> mRecordTrack;
+ };
+
+ // record thread
+ class AudioRecordThread : public Thread
+ {
+ public:
+ AudioRecordThread(AudioHardwareInterface* audioHardware);
+ virtual ~AudioRecordThread();
+ virtual bool threadLoop();
+ virtual status_t readyToRun() { return NO_ERROR; }
+ virtual void onFirstRef() {}
+
+ status_t start(MixerThread::RecordTrack* recordTrack);
+ void stop(MixerThread::RecordTrack* recordTrack);
+ void exit();
+ status_t dump(int fd, const Vector<String16>& args);
+
+ private:
+ AudioRecordThread();
+ AudioHardwareInterface *mAudioHardware;
+ sp<MixerThread::RecordTrack> mRecordTrack;
+ Mutex mLock;
+ Condition mWaitWorkCV;
+ Condition mStopped;
+ volatile bool mActive;
+ status_t mStartStatus;
+ };
+
+ friend class AudioRecordThread;
+ friend class MixerThread;
+
+ status_t startRecord(MixerThread::RecordTrack* recordTrack);
+ void stopRecord(MixerThread::RecordTrack* recordTrack);
+
+ void handleOutputSwitch();
+
+ mutable Mutex mHardwareLock;
+ mutable Mutex mLock;
+ DefaultKeyedVector< pid_t, wp<Client> > mClients;
+
+ sp<MixerThread> mA2dpMixerThread;
+ sp<MixerThread> mHardwareMixerThread;
+ AudioHardwareInterface* mAudioHardware;
+ AudioHardwareInterface* mA2dpAudioInterface;
+ sp<AudioRecordThread> mAudioRecordThread;
+ bool mA2dpEnabled;
+ bool mA2dpEnabledReq;
+ mutable int mHardwareStatus;
+ SortedVector< wp<IBinder> > mNotificationClients;
+ int mForcedSpeakerCount;
+ uint32_t mSavedRoute;
+ uint32_t mForcedRoute;
+ nsecs_t mRouteRestoreTime;
+ bool mMusicMuteSaved;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_FLINGER_H