summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/Threads.h
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-05-08 18:49:52 -0700
committerEric Laurent <elaurent@google.com>2014-05-09 15:25:49 -0700
commit1035194cee4fbd57e35ea15c56e66cd09b63d56e (patch)
treed443c6a41767ab240292494155885f65f88d7e76 /services/audioflinger/Threads.h
parentd283f68057204fcde95e6c9ba79a59f27ae58fe3 (diff)
downloadframeworks_av-1035194cee4fbd57e35ea15c56e66cd09b63d56e.zip
frameworks_av-1035194cee4fbd57e35ea15c56e66cd09b63d56e.tar.gz
frameworks_av-1035194cee4fbd57e35ea15c56e66cd09b63d56e.tar.bz2
audioflinger: refactor thread config events
Merge config events and set parameters messaging mechanism. - setting parameters now uses the config event mechanism - config event now allow to wait for a condition and synchronize caller binder thread with execution thread and return an execution status. - simplify locking mechanism to avoid unlocking the thread mutex while processing events. Change-Id: Ia49cb3e617abec4bacb6c1f9a8cb304c4ed3902e
Diffstat (limited to 'services/audioflinger/Threads.h')
-rw-r--r--services/audioflinger/Threads.h171
1 files changed, 114 insertions, 57 deletions
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 8ea8683..9578993 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -46,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(param) {}
- 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:
@@ -135,15 +196,25 @@ 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_l(
+ const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
+ 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();
- void processConfigEvents_l();
+ status_t sendSetParameterConfigEvent_l(const String8& keyValuePair);
+ void processConfigEvents_l(
+ const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients);
+ virtual void cacheParameters_l() = 0;
// see note at declaration of mStandby, mOutDevice and mInDevice
bool standby() const { return mStandby; }
@@ -287,31 +358,7 @@ protected:
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()
@@ -455,7 +502,10 @@ 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_l(
+ const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
+ int event,
+ int param = 0);
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
// FIXME rename mixBuffer() to sinkBuffer() and remove int16_t* dependency.
// Consider also removing and passing an explicit mMainBuffer initialization
@@ -724,7 +774,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:
@@ -778,7 +829,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);
@@ -981,9 +1033,14 @@ public:
virtual audio_stream_t* stream() const;
- 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);
+ virtual void audioConfigChanged_l(
+ const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
+ int event,
+ int param = 0);
void readInputParameters_l();
virtual uint32_t getInputFramesLost();