summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/Threads.h
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger/Threads.h')
-rw-r--r--services/audioflinger/Threads.h345
1 files changed, 231 insertions, 114 deletions
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index a2fb874..cc2b246 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -36,6 +36,8 @@ public:
audio_devices_t outDevice, audio_devices_t inDevice, type_t type);
virtual ~ThreadBase();
+ virtual status_t readyToRun();
+
void dumpBase(int fd, const Vector<String16>& args);
void dumpEffectChains(int fd, const Vector<String16>& args);
@@ -44,60 +46,121 @@ public:
// base for record and playback
enum {
CFG_EVENT_IO,
- CFG_EVENT_PRIO
+ CFG_EVENT_PRIO,
+ CFG_EVENT_SET_PARAMETER,
};
- class ConfigEvent {
+ class ConfigEventData: public RefBase {
+ public:
+ virtual ~ConfigEventData() {}
+
+ virtual void dump(char *buffer, size_t size) = 0;
+ protected:
+ ConfigEventData() {}
+ };
+
+ // Config event sequence by client if status needed (e.g binder thread calling setParameters()):
+ // 1. create SetParameterConfigEvent. This sets mWaitStatus in config event
+ // 2. Lock mLock
+ // 3. Call sendConfigEvent_l(): Append to mConfigEvents and mWaitWorkCV.signal
+ // 4. sendConfigEvent_l() reads status from event->mStatus;
+ // 5. sendConfigEvent_l() returns status
+ // 6. Unlock
+ //
+ // Parameter sequence by server: threadLoop calling processConfigEvents_l():
+ // 1. Lock mLock
+ // 2. If there is an entry in mConfigEvents proceed ...
+ // 3. Read first entry in mConfigEvents
+ // 4. Remove first entry from mConfigEvents
+ // 5. Process
+ // 6. Set event->mStatus
+ // 7. event->mCond.signal
+ // 8. Unlock
+
+ class ConfigEvent: public RefBase {
public:
- ConfigEvent(int type) : mType(type) {}
virtual ~ConfigEvent() {}
- int type() const { return mType; }
+ void dump(char *buffer, size_t size) { mData->dump(buffer, size); }
- virtual void dump(char *buffer, size_t size) = 0;
+ const int mType; // event type e.g. CFG_EVENT_IO
+ Mutex mLock; // mutex associated with mCond
+ Condition mCond; // condition for status return
+ status_t mStatus; // status communicated to sender
+ bool mWaitStatus; // true if sender is waiting for status
+ sp<ConfigEventData> mData; // event specific parameter data
- private:
- const int mType;
+ protected:
+ ConfigEvent(int type) : mType(type), mStatus(NO_ERROR), mWaitStatus(false), mData(NULL) {}
};
- class IoConfigEvent : public ConfigEvent {
+ class IoConfigEventData : public ConfigEventData {
public:
- IoConfigEvent(int event, int param) :
- ConfigEvent(CFG_EVENT_IO), mEvent(event), mParam(event) {}
- virtual ~IoConfigEvent() {}
-
- int event() const { return mEvent; }
- int param() const { return mParam; }
+ IoConfigEventData(int event, int param) :
+ mEvent(event), mParam(param) {}
virtual void dump(char *buffer, size_t size) {
snprintf(buffer, size, "IO event: event %d, param %d\n", mEvent, mParam);
}
- private:
const int mEvent;
const int mParam;
};
- class PrioConfigEvent : public ConfigEvent {
+ class IoConfigEvent : public ConfigEvent {
public:
- PrioConfigEvent(pid_t pid, pid_t tid, int32_t prio) :
- ConfigEvent(CFG_EVENT_PRIO), mPid(pid), mTid(tid), mPrio(prio) {}
- virtual ~PrioConfigEvent() {}
+ IoConfigEvent(int event, int param) :
+ ConfigEvent(CFG_EVENT_IO) {
+ mData = new IoConfigEventData(event, param);
+ }
+ virtual ~IoConfigEvent() {}
+ };
- pid_t pid() const { return mPid; }
- pid_t tid() const { return mTid; }
- int32_t prio() const { return mPrio; }
+ class PrioConfigEventData : public ConfigEventData {
+ public:
+ PrioConfigEventData(pid_t pid, pid_t tid, int32_t prio) :
+ mPid(pid), mTid(tid), mPrio(prio) {}
virtual void dump(char *buffer, size_t size) {
snprintf(buffer, size, "Prio event: pid %d, tid %d, prio %d\n", mPid, mTid, mPrio);
}
- private:
const pid_t mPid;
const pid_t mTid;
const int32_t mPrio;
};
+ class PrioConfigEvent : public ConfigEvent {
+ public:
+ PrioConfigEvent(pid_t pid, pid_t tid, int32_t prio) :
+ ConfigEvent(CFG_EVENT_PRIO) {
+ mData = new PrioConfigEventData(pid, tid, prio);
+ }
+ virtual ~PrioConfigEvent() {}
+ };
+
+ class SetParameterConfigEventData : public ConfigEventData {
+ public:
+ SetParameterConfigEventData(String8 keyValuePairs) :
+ mKeyValuePairs(keyValuePairs) {}
+
+ virtual void dump(char *buffer, size_t size) {
+ snprintf(buffer, size, "KeyValue: %s\n", mKeyValuePairs.string());
+ }
+
+ const String8 mKeyValuePairs;
+ };
+
+ class SetParameterConfigEvent : public ConfigEvent {
+ public:
+ SetParameterConfigEvent(String8 keyValuePairs) :
+ ConfigEvent(CFG_EVENT_SET_PARAMETER) {
+ mData = new SetParameterConfigEventData(keyValuePairs);
+ mWaitStatus = true;
+ }
+ virtual ~SetParameterConfigEvent() {}
+ };
+
class PMDeathRecipient : public IBinder::DeathRecipient {
public:
@@ -133,14 +196,21 @@ public:
// Should be "virtual status_t requestExitAndWait()" and override same
// method in Thread, but Thread::requestExitAndWait() is not yet virtual.
void exit();
- virtual bool checkForNewParameters_l() = 0;
+ virtual bool checkForNewParameter_l(const String8& keyValuePair,
+ status_t& status) = 0;
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys) = 0;
- virtual void audioConfigChanged_l(int event, int param = 0) = 0;
+ virtual void audioConfigChanged(int event, int param = 0) = 0;
+ // sendConfigEvent_l() must be called with ThreadBase::mLock held
+ // Can temporarily release the lock if waiting for a reply from
+ // processConfigEvents_l().
+ status_t sendConfigEvent_l(sp<ConfigEvent>& event);
void sendIoConfigEvent(int event, int param = 0);
void sendIoConfigEvent_l(int event, int param = 0);
void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);
- void processConfigEvents();
+ status_t sendSetParameterConfigEvent_l(const String8& keyValuePair);
+ void processConfigEvents_l();
+ virtual void cacheParameters_l() = 0;
// see note at declaration of mStandby, mOutDevice and mInDevice
bool standby() const { return mStandby; }
@@ -156,7 +226,7 @@ public:
int sessionId,
effect_descriptor_t *desc,
int *enabled,
- status_t *status);
+ status_t *status /*non-NULL*/);
void disconnectEffect(const sp< EffectModule>& effect,
EffectHandle *handle,
bool unpinIfLast);
@@ -198,13 +268,13 @@ public:
// effect
void removeEffect_l(const sp< EffectModule>& effect);
// detach all tracks connected to an auxiliary effect
- virtual void detachAuxEffect_l(int effectId) {}
+ virtual void detachAuxEffect_l(int effectId __unused) {}
// returns either EFFECT_SESSION if effects on this audio session exist in one
// chain, or TRACK_SESSION if tracks on this audio session exist, or both
virtual uint32_t hasAudioSession(int sessionId) const = 0;
// the value returned by default implementation is not important as the
// strategy is only meaningful for PlaybackThread which implements this method
- virtual uint32_t getStrategyForSession_l(int sessionId) { return 0; }
+ virtual uint32_t getStrategyForSession_l(int sessionId __unused) { return 0; }
// suspend or restore effect according to the type of effect passed. a NULL
// type pointer means suspend all effects in the session
@@ -223,6 +293,13 @@ public:
virtual status_t setSyncEvent(const sp<SyncEvent>& event) = 0;
virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const = 0;
+ // Return a reference to a per-thread heap which can be used to allocate IMemory
+ // objects that will be read-only to client processes, read/write to mediaserver,
+ // and shared by all client processes of the thread.
+ // The heap is per-thread rather than common across all threads, because
+ // clients can't be trusted not to modify the offset of the IMemory they receive.
+ // If a thread does not have such a heap, this method returns 0.
+ virtual sp<MemoryDealer> readOnlyHeap() const { return 0; }
mutable Mutex mLock;
@@ -267,48 +344,25 @@ protected:
const sp<AudioFlinger> mAudioFlinger;
- // updated by PlaybackThread::readOutputParameters() or
- // RecordThread::readInputParameters()
+ // updated by PlaybackThread::readOutputParameters_l() or
+ // RecordThread::readInputParameters_l()
uint32_t mSampleRate;
size_t mFrameCount; // output HAL, direct output, record
audio_channel_mask_t mChannelMask;
uint32_t mChannelCount;
size_t mFrameSize;
audio_format_t mFormat;
+ size_t mBufferSize; // HAL buffer size for read() or write()
- // Parameter sequence by client: binder thread calling setParameters():
- // 1. Lock mLock
- // 2. Append to mNewParameters
- // 3. mWaitWorkCV.signal
- // 4. mParamCond.waitRelative with timeout
- // 5. read mParamStatus
- // 6. mWaitWorkCV.signal
- // 7. Unlock
- //
- // Parameter sequence by server: threadLoop calling checkForNewParameters_l():
- // 1. Lock mLock
- // 2. If there is an entry in mNewParameters proceed ...
- // 2. Read first entry in mNewParameters
- // 3. Process
- // 4. Remove first entry from mNewParameters
- // 5. Set mParamStatus
- // 6. mParamCond.signal
- // 7. mWaitWorkCV.wait with timeout (this is to avoid overwriting mParamStatus)
- // 8. Unlock
- Condition mParamCond;
- Vector<String8> mNewParameters;
- status_t mParamStatus;
-
- // vector owns each ConfigEvent *, so must delete after removing
- Vector<ConfigEvent *> mConfigEvents;
+ Vector< sp<ConfigEvent> > mConfigEvents;
// These fields are written and read by thread itself without lock or barrier,
- // and read by other threads without lock or barrier via standby() , outDevice()
+ // and read by other threads without lock or barrier via standby(), outDevice()
// and inDevice().
// Because of the absence of a lock or barrier, any other thread that reads
// these fields must use the information in isolation, or be prepared to deal
// with possibility that it might be inconsistent with other information.
- bool mStandby; // Whether thread is currently in standby.
+ bool mStandby; // Whether thread is currently in standby.
audio_devices_t mOutDevice; // output device
audio_devices_t mInDevice; // input device
audio_source_t mAudioSource; // (see audio.h, audio_source_t)
@@ -358,7 +412,6 @@ public:
void dump(int fd, const Vector<String16>& args);
// Thread virtuals
- virtual status_t readyToRun();
virtual bool threadLoop();
// RefBase
@@ -391,7 +444,7 @@ protected:
virtual bool waitingAsyncCallback();
virtual bool waitingAsyncCallback_l();
virtual bool shouldStandby_l();
-
+ virtual void onAddNewTrack_l();
// ThreadBase virtuals
virtual void preExit();
@@ -419,13 +472,13 @@ public:
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
- size_t frameCount,
+ size_t *pFrameCount,
const sp<IMemory>& sharedBuffer,
int sessionId,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
int uid,
- status_t *status);
+ status_t *status /*non-NULL*/);
AudioStreamOut* getOutput() const;
AudioStreamOut* clearOutput();
@@ -445,9 +498,13 @@ public:
{ return android_atomic_acquire_load(&mSuspended) > 0; }
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged_l(int event, int param = 0);
+ virtual void audioConfigChanged(int event, int param = 0);
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
- int16_t *mixBuffer() const { return mMixBuffer; };
+ // FIXME rename mixBuffer() to sinkBuffer() and remove int16_t* dependency.
+ // Consider also removing and passing an explicit mMainBuffer initialization
+ // parameter to AF::PlaybackThread::Track::Track().
+ int16_t *mixBuffer() const {
+ return reinterpret_cast<int16_t *>(mSinkBuffer); };
virtual void detachAuxEffect_l(int effectId);
status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track,
@@ -475,11 +532,68 @@ public:
status_t getTimestamp_l(AudioTimestamp& timestamp);
protected:
- // updated by readOutputParameters()
+ // updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
- int16_t* mMixBuffer; // frame size aligned mix buffer
- int8_t* mAllocMixBuffer; // mixer buffer allocation address
+ void* mSinkBuffer; // frame size aligned sink buffer
+
+ // TODO:
+ // Rearrange the buffer info into a struct/class with
+ // clear, copy, construction, destruction methods.
+ //
+ // mSinkBuffer also has associated with it:
+ //
+ // mSinkBufferSize: Sink Buffer Size
+ // mFormat: Sink Buffer Format
+
+ // Mixer Buffer (mMixerBuffer*)
+ //
+ // In the case of floating point or multichannel data, which is not in the
+ // sink format, it is required to accumulate in a higher precision or greater channel count
+ // buffer before downmixing or data conversion to the sink buffer.
+
+ // Set to "true" to enable the Mixer Buffer otherwise mixer output goes to sink buffer.
+ bool mMixerBufferEnabled;
+
+ // Storage, 32 byte aligned (may make this alignment a requirement later).
+ // Due to constraints on mNormalFrameCount, the buffer size is a multiple of 16 frames.
+ void* mMixerBuffer;
+
+ // Size of mMixerBuffer in bytes: mNormalFrameCount * #channels * sampsize.
+ size_t mMixerBufferSize;
+
+ // The audio format of mMixerBuffer. Set to AUDIO_FORMAT_PCM_(FLOAT|16_BIT) only.
+ audio_format_t mMixerBufferFormat;
+
+ // An internal flag set to true by MixerThread::prepareTracks_l()
+ // when mMixerBuffer contains valid data after mixing.
+ bool mMixerBufferValid;
+
+ // Effects Buffer (mEffectsBuffer*)
+ //
+ // In the case of effects data, which is not in the sink format,
+ // it is required to accumulate in a different buffer before data conversion
+ // to the sink buffer.
+
+ // Set to "true" to enable the Effects Buffer otherwise effects output goes to sink buffer.
+ bool mEffectBufferEnabled;
+
+ // Storage, 32 byte aligned (may make this alignment a requirement later).
+ // Due to constraints on mNormalFrameCount, the buffer size is a multiple of 16 frames.
+ void* mEffectBuffer;
+
+ // Size of mEffectsBuffer in bytes: mNormalFrameCount * #channels * sampsize.
+ size_t mEffectBufferSize;
+
+ // The audio format of mEffectsBuffer. Set to AUDIO_FORMAT_PCM_16_BIT only.
+ audio_format_t mEffectBufferFormat;
+
+ // An internal flag set to true by MixerThread::prepareTracks_l()
+ // when mEffectsBuffer contains valid data after mixing.
+ //
+ // When this is set, all mixer data is routed into the effects buffer
+ // for any processing (including output processing).
+ bool mEffectBufferValid;
// suspend count, > 0 means suspended. While suspended, the thread continues to pull from
// tracks and mix, but doesn't write to HAL. A2DP and SCO HAL implementations can't handle
@@ -531,7 +645,6 @@ private:
friend class AudioFlinger; // for numerous
- PlaybackThread(const Client&);
PlaybackThread& operator = (const PlaybackThread&);
status_t addTrack_l(const sp<Track>& track);
@@ -539,7 +652,7 @@ private:
void removeTrack_l(const sp<Track>& track);
void broadcast_l();
- void readOutputParameters();
+ void readOutputParameters_l();
virtual void dumpInternals(int fd, const Vector<String16>& args);
void dumpTracks(int fd, const Vector<String16>& args);
@@ -558,7 +671,7 @@ private:
// FIXME rename these former local variables of threadLoop to standard "m" names
nsecs_t standbyTime;
- size_t mixBufferSize;
+ size_t mSinkBufferSize;
// cached copies of activeSleepTimeUs() and idleSleepTimeUs() made by cacheParameters_l()
uint32_t activeSleepTime;
@@ -623,13 +736,12 @@ private:
sp<NBLog::Writer> mFastMixerNBLogWriter;
public:
virtual bool hasFastMixer() const = 0;
- virtual FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex) const
+ virtual FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex __unused) const
{ FastTrackUnderruns dummy; return dummy; }
protected:
// accessed by both binder threads and within threadLoop(), lock on mutex needed
unsigned mFastTrackAvailMask; // bit i set if fast track [i] is available
- virtual void flushOutput_l();
private:
// timestamp latch:
@@ -654,7 +766,8 @@ public:
// Thread virtuals
- virtual bool checkForNewParameters_l();
+ virtual bool checkForNewParameter_l(const String8& keyValuePair,
+ status_t& status);
virtual void dumpInternals(int fd, const Vector<String16>& args);
protected:
@@ -708,7 +821,8 @@ public:
// Thread virtuals
- virtual bool checkForNewParameters_l();
+ virtual bool checkForNewParameter_l(const String8& keyValuePair,
+ status_t& status);
protected:
virtual int getTrackName_l(audio_channel_mask_t channelMask, int sessionId);
@@ -748,11 +862,11 @@ protected:
// threadLoop snippets
virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
virtual void threadLoop_exit();
- virtual void flushOutput_l();
virtual bool waitingAsyncCallback();
virtual bool waitingAsyncCallback_l();
virtual bool shouldStandby_l();
+ virtual void onAddNewTrack_l();
private:
void flushHw_l();
@@ -838,17 +952,28 @@ public:
// record thread
-class RecordThread : public ThreadBase, public AudioBufferProvider
- // derives from AudioBufferProvider interface for use by resampler
+class RecordThread : public ThreadBase
{
public:
+ class RecordTrack;
+ class ResamplerBufferProvider : public AudioBufferProvider
+ // derives from AudioBufferProvider interface for use by resampler
+ {
+ public:
+ ResamplerBufferProvider(RecordTrack* recordTrack) : mRecordTrack(recordTrack) { }
+ virtual ~ResamplerBufferProvider() { }
+ // AudioBufferProvider interface
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts);
+ virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+ private:
+ RecordTrack * const mRecordTrack;
+ };
+
#include "RecordTracks.h"
RecordThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamIn *input,
- uint32_t sampleRate,
- audio_channel_mask_t channelMask,
audio_io_handle_t id,
audio_devices_t outDevice,
audio_devices_t inDevice
@@ -867,23 +992,25 @@ public:
// Thread virtuals
virtual bool threadLoop();
- virtual status_t readyToRun();
// RefBase
virtual void onFirstRef();
virtual status_t initCheck() const { return (mInput == NULL) ? NO_INIT : NO_ERROR; }
+
+ virtual sp<MemoryDealer> readOnlyHeap() const { return mReadOnlyHeap; }
+
sp<AudioFlinger::RecordThread::RecordTrack> createRecordTrack_l(
const sp<AudioFlinger::Client>& client,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
- size_t frameCount,
+ size_t *pFrameCount,
int sessionId,
int uid,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
- status_t *status);
+ status_t *status /*non-NULL*/);
status_t start(RecordTrack* recordTrack,
AudioSystem::sync_event_t event,
@@ -897,15 +1024,14 @@ public:
AudioStreamIn* clearInput();
virtual audio_stream_t* stream() const;
- // AudioBufferProvider interface
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts);
- virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
- virtual bool checkForNewParameters_l();
+ virtual bool checkForNewParameter_l(const String8& keyValuePair,
+ status_t& status);
+ virtual void cacheParameters_l() {}
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged_l(int event, int param = 0);
- void readInputParameters();
- virtual unsigned int getInputFramesLost();
+ virtual void audioConfigChanged(int event, int param = 0);
+ void readInputParameters_l();
+ virtual uint32_t getInputFramesLost();
virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
@@ -920,45 +1046,36 @@ public:
virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
static void syncStartEventCallback(const wp<SyncEvent>& event);
- void handleSyncStartEvent(const sp<SyncEvent>& event);
virtual size_t frameCount() const { return mFrameCount; }
- bool hasFastRecorder() const { return false; }
+ bool hasFastCapture() const { return false; }
private:
- void clearSyncStartEvent();
-
// Enter standby if not already in standby, and set mStandby flag
- void standby();
+ void standbyIfNotAlreadyInStandby();
// Call the HAL standby method unconditionally, and don't change mStandby flag
- void inputStandBy();
+ void inputStandBy();
AudioStreamIn *mInput;
SortedVector < sp<RecordTrack> > mTracks;
- // mActiveTrack has dual roles: it indicates the current active track, and
+ // mActiveTracks has dual roles: it indicates the current active track(s), and
// is used together with mStartStopCond to indicate start()/stop() progress
- sp<RecordTrack> mActiveTrack;
+ SortedVector< sp<RecordTrack> > mActiveTracks;
+ // generation counter for mActiveTracks
+ int mActiveTracksGen;
Condition mStartStopCond;
- // updated by RecordThread::readInputParameters()
- AudioResampler *mResampler;
- // interleaved stereo pairs of fixed-point signed Q19.12
- int32_t *mRsmpOutBuffer;
- int16_t *mRsmpInBuffer; // [mFrameCount * mChannelCount]
- size_t mRsmpInIndex;
- size_t mBufferSize; // stream buffer size for read()
- const uint32_t mReqChannelCount;
- const uint32_t mReqSampleRate;
- ssize_t mBytesRead;
- // sync event triggering actual audio capture. Frames read before this event will
- // be dropped and therefore not read by the application.
- sp<SyncEvent> mSyncStartEvent;
- // number of captured frames to drop after the start sync event has been received.
- // when < 0, maximum frames to drop before starting capture even if sync event is
- // not received
- ssize_t mFramestoDrop;
+ // resampler converts input at HAL Hz to output at AudioRecord client Hz
+ int16_t *mRsmpInBuffer; // see new[] for details on the size
+ size_t mRsmpInFrames; // size of resampler input in frames
+ size_t mRsmpInFramesP2;// size rounded up to a power-of-2
+
+ // rolling index that is never cleared
+ int32_t mRsmpInRear; // last filled frame + 1
// For dumpsys
const sp<NBAIO_Sink> mTeeSink;
+
+ const sp<MemoryDealer> mReadOnlyHeap;
};