auto import from //branches/cupcake/...@131421
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 38fa001..3b5932d 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -33,6 +33,7 @@
#include <utils/MemoryDealer.h>
#include <utils/KeyedVector.h>
#include <utils/SortedVector.h>
+#include <utils/Vector.h>
#include <hardware_legacy/AudioHardwareInterface.h>
@@ -55,18 +56,13 @@
static const nsecs_t kStandbyTimeInNsecs = seconds(3);
-class AudioFlinger : public BnAudioFlinger, protected Thread, public IBinder::DeathRecipient
+class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient
{
public:
static void instantiate();
virtual status_t dump(int fd, const Vector<String16>& args);
- // Thread virtuals
- virtual bool threadLoop();
- virtual status_t readyToRun();
- virtual void onFirstRef();
-
// IAudioFlinger interface
virtual sp<IAudioTrack> createTrack(
pid_t pid,
@@ -79,11 +75,11 @@
const sp<IMemory>& sharedBuffer,
status_t *status);
- virtual uint32_t sampleRate() const;
- virtual int channelCount() const;
- virtual int format() const;
- virtual size_t frameCount() const;
- virtual size_t latency() const;
+ 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);
@@ -108,6 +104,8 @@
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);
@@ -159,23 +157,26 @@
AudioFlinger();
virtual ~AudioFlinger();
- void setOutput(AudioStreamOut* output);
- void doSetOutput(AudioStreamOut* output);
- size_t getOutputFrameCount(AudioStreamOut* output);
+ void setOutput(int outputType);
+ void doSetOutput(int outputType);
#ifdef WITH_A2DP
- static bool streamDisablesA2dp(int streamType);
- inline bool isA2dpEnabled() const {
- return (mRequestedOutput == mA2dpOutput ||
- (mOutput && mOutput == mA2dpOutput));
- }
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 dumpTracks(int fd, const Vector<String16>& args);
status_t dumpInternals(int fd, const Vector<String16>& args);
// --- Client ---
@@ -194,168 +195,348 @@
};
- // --- Track ---
class TrackHandle;
class RecordHandle;
class AudioRecordThread;
- // base for record and playback
- class TrackBase : public AudioBufferProvider, public RefBase {
-
+
+ // --- MixerThread ---
+ class MixerThread : public Thread {
public:
- enum track_state {
- IDLE,
- TERMINATED,
- STOPPED,
- RESUMING,
- ACTIVE,
- PAUSING,
- PAUSED
+
+ // --- 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
+ };
+
+ TrackBase( const sp<MixerThread>& mixerThread,
+ const sp<Client>& client,
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount,
+ 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;
+ uint8_t mFlags;
};
- enum track_flags {
- STEPSERVER_FAILED = 0x01 // StepServer could not acquire cblk->lock mutex
+ // 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);
+ ~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;
};
- TrackBase( const sp<AudioFlinger>& audioFlinger,
- const sp<Client>& client,
+ // 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);
- ~TrackBase();
+ const sp<IMemory>& sharedBuffer,
+ status_t *status);
- virtual status_t start() = 0;
- virtual void stop() = 0;
- sp<IMemory> getCblk() const;
-
- protected:
- friend class AudioFlinger;
- 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<AudioFlinger> mAudioFlinger;
- 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;
- uint8_t mFlags;
- };
-
- // playback track
- class Track : public TrackBase {
- public:
- Track( const sp<AudioFlinger>& audioFlinger,
- 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);
+ 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 TrackHandle;
+ 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();
- Track(const Track&);
- Track& operator = (const Track&);
+ 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;
+ };
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
- bool isMuted() const {
- return (mMute || mAudioFlinger->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
-
+
friend class AudioBuffer;
class TrackHandle : public android::BnAudioTrack {
public:
- TrackHandle(const sp<Track>& track);
+ TrackHandle(const sp<MixerThread::Track>& track);
virtual ~TrackHandle();
virtual status_t start();
virtual void stop();
@@ -367,72 +548,20 @@
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
private:
- sp<Track> mTrack;
- };
-
- struct stream_type_t {
- stream_type_t()
- : volume(1.0f),
- mute(false)
- {
- }
- float volume;
- bool mute;
+ sp<MixerThread::Track> mTrack;
};
friend class Client;
- friend class Track;
+ friend class MixerThread::Track;
void removeClient(pid_t pid);
- 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);
- void addActiveTrack(const wp<Track>& track);
- void removeActiveTrack(const wp<Track>& track);
- int getTrackName();
- void deleteTrackName(int name);
- AudioMixer* audioMixer() {
- return mAudioMixer;
- }
-
- // record track
- class RecordTrack : public TrackBase {
- public:
- RecordTrack( const sp<AudioFlinger>& audioFlinger,
- const sp<Client>& client,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount);
- ~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 RecordHandle;
- friend class AudioRecordThread;
-
- RecordTrack(const Track&);
- RecordTrack& operator = (const Track&);
-
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
- bool mOverflow;
- };
class RecordHandle : public android::BnAudioRecord {
public:
- RecordHandle(const sp<RecordTrack>& recordTrack);
+ RecordHandle(const sp<MixerThread::RecordTrack>& recordTrack);
virtual ~RecordHandle();
virtual status_t start();
virtual void stop();
@@ -440,7 +569,7 @@
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
private:
- sp<RecordTrack> mRecordTrack;
+ sp<MixerThread::RecordTrack> mRecordTrack;
};
// record thread
@@ -453,14 +582,14 @@
virtual status_t readyToRun() { return NO_ERROR; }
virtual void onFirstRef() {}
- status_t start(RecordTrack* recordTrack);
- void stop(RecordTrack* recordTrack);
+ status_t start(MixerThread::RecordTrack* recordTrack);
+ void stop(MixerThread::RecordTrack* recordTrack);
void exit();
private:
AudioRecordThread();
AudioHardwareInterface *mAudioHardware;
- sp<RecordTrack> mRecordTrack;
+ sp<MixerThread::RecordTrack> mRecordTrack;
Mutex mLock;
Condition mWaitWorkCV;
volatile bool mActive;
@@ -468,48 +597,31 @@
};
friend class AudioRecordThread;
+ friend class MixerThread;
- status_t startRecord(RecordTrack* recordTrack);
- void stopRecord(RecordTrack* recordTrack);
-
- void notifyOutputChange_l();
+ status_t startRecord(MixerThread::RecordTrack* recordTrack);
+ void stopRecord(MixerThread::RecordTrack* recordTrack);
+
+ void handleOutputSwitch();
mutable Mutex mHardwareLock;
mutable Mutex mLock;
- mutable Condition mWaitWorkCV;
DefaultKeyedVector< pid_t, wp<Client> > mClients;
- SortedVector< wp<Track> > mActiveTracks;
- SortedVector< sp<Track> > mTracks;
- float mMasterVolume;
- uint32_t mMasterRouting;
- bool mMasterMute;
- stream_type_t mStreamTypes[AudioTrack::NUM_STREAM_TYPES];
- AudioMixer* mHardwareAudioMixer;
- AudioMixer* mA2dpAudioMixer;
- AudioMixer* mAudioMixer;
+ sp<MixerThread> mA2dpMixerThread;
+ sp<MixerThread> mHardwareMixerThread;
AudioHardwareInterface* mAudioHardware;
AudioHardwareInterface* mA2dpAudioInterface;
- AudioStreamOut* mHardwareOutput;
- AudioStreamOut* mA2dpOutput;
- AudioStreamOut* mOutput;
- AudioStreamOut* mRequestedOutput;
sp<AudioRecordThread> mAudioRecordThread;
- uint32_t mSampleRate;
- size_t mFrameCount;
- int mChannelCount;
- int mFormat;
- int16_t* mMixBuffer;
+ bool mA2dpEnabled;
+ bool mA2dpEnabledReq;
mutable int mHardwareStatus;
- nsecs_t mLastWriteTime;
- int mNumWrites;
- int mNumDelayedWrites;
- bool mStandby;
- bool mInWrite;
- int mA2dpDisableCount;
- bool mA2dpSuppressed;
- bool mMusicMuteSaved;
SortedVector< wp<IBinder> > mNotificationClients;
+ int mForcedSpeakerCount;
+ uint32_t mSavedRoute;
+ uint32_t mForcedRoute;
+ nsecs_t mRouteRestoreTime;
+ bool mMusicMuteSaved;
};
// ----------------------------------------------------------------------------