Loading services/audioflinger/AudioFlinger.cpp +14 −9 Original line number Diff line number Diff line Loading @@ -1195,11 +1195,16 @@ void AudioFlinger::removeNotificationClient(pid_t pid) } // audioConfigChanged_l() must be called with AudioFlinger::mLock held void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2) void AudioFlinger::audioConfigChanged_l( const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients, int event, audio_io_handle_t ioHandle, const void *param2) { size_t size = mNotificationClients.size(); size_t size = notificationClients.size(); for (size_t i = 0; i < size; i++) { mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle, notificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle, param2); } } Loading Loading @@ -1633,7 +1638,7 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, } // notify client processes of the new output creation thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); thread->audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_OPENED); // the first primary output opened designates the primary hw device if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) { Loading Loading @@ -1669,7 +1674,7 @@ audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1, thread->addOutputTrack(thread2); mPlaybackThreads.add(id, thread); // notify client processes of the new output creation thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); thread->audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_OPENED); return id; } Loading Loading @@ -1719,7 +1724,7 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output) } } } audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL); audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_CLOSED, output, NULL); } thread->exit(); // The thread entity (active unit of execution) is no longer running here, Loading Loading @@ -1899,7 +1904,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, } // notify client processes of the new input creation thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED); thread->audioConfigChanged_l(mNotificationClients, AudioSystem::INPUT_OPENED); return id; } Loading @@ -1924,7 +1929,7 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input) } ALOGV("closeInput() %d", input); audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, NULL); audioConfigChanged_l(mNotificationClients, AudioSystem::INPUT_CLOSED, input, NULL); mRecordThreads.removeItem(input); } thread->exit(); Loading services/audioflinger/AudioFlinger.h +7 −2 Original line number Diff line number Diff line Loading @@ -454,7 +454,11 @@ private: // no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held float streamVolume_l(audio_stream_type_t stream) const { return mStreamTypes[stream].volume; } void audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2); void audioConfigChanged_l(const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients, int event, audio_io_handle_t ioHandle, const void *param2); // Allocate an audio_io_handle_t, session ID, effect ID, or audio_module_handle_t. // They all share the same ID space, but the namespaces are actually independent Loading @@ -479,7 +483,8 @@ private: void removeClient_l(pid_t pid); void removeNotificationClient(pid_t pid); DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients() { Mutex::Autolock _l(mLock); return mNotificationClients; } bool isNonOffloadableGlobalEffectEnabled_l(); void onNonOffloadableGlobalEffectEnable(); Loading services/audioflinger/Threads.cpp +301 −316 Original line number Diff line number Diff line Loading @@ -97,8 +97,8 @@ static const nsecs_t kWarningThrottleNs = seconds(5); // RecordThread loop sleep time upon application overrun or audio HAL read error static const int kRecordThreadSleepUs = 5000; // maximum time to wait for setParameters to complete static const nsecs_t kSetParametersTimeoutNs = seconds(2); // maximum time to wait in sendConfigEvent_l() for a status to be received static const nsecs_t kConfigEventTimeoutNs = seconds(2); // minimum sleep time for the mixer thread loop when tracks are active but in underrun static const uint32_t kMinThreadSleepTimeUs = 5000; Loading Loading @@ -283,7 +283,6 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio // mSampleRate, mFrameCount, mChannelMask, mChannelCount, mFrameSize, mFormat, mBufferSize // are set by PlaybackThread::readOutputParameters_l() or // RecordThread::readInputParameters_l() mParamStatus(NO_ERROR), //FIXME: mStandby should be true here. Is this some kind of hack? mStandby(false), mOutDevice(outDevice), mInDevice(inDevice), mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), Loading @@ -295,12 +294,8 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio AudioFlinger::ThreadBase::~ThreadBase() { // mConfigEvents should be empty, but just in case it isn't, free the memory it owns for (size_t i = 0; i < mConfigEvents.size(); i++) { delete mConfigEvents[i]; } mConfigEvents.clear(); mParamCond.broadcast(); // do not lock the mutex in destructor releaseWakeLock_l(); if (mPowerManager != 0) { Loading Loading @@ -351,16 +346,30 @@ status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs) ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string()); Mutex::Autolock _l(mLock); mNewParameters.add(keyValuePairs); mWaitWorkCV.signal(); // wait condition with timeout in case the thread loop has exited // before the request could be processed if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) { status = mParamStatus; return sendSetParameterConfigEvent_l(keyValuePairs); } // sendConfigEvent_l() must be called with ThreadBase::mLock held // Can temporarily release the lock if waiting for a reply from processConfigEvents_l(). status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event) { status_t status = NO_ERROR; mConfigEvents.add(event); ALOGV("sendConfigEvent_l() num events %d event %d", mConfigEvents.size(), event->mType); mWaitWorkCV.signal(); } else { status = TIMED_OUT; mLock.unlock(); { Mutex::Autolock _l(event->mLock); while (event->mWaitStatus) { if (event->mCond.waitRelative(event->mLock, kConfigEventTimeoutNs) != NO_ERROR) { event->mStatus = TIMED_OUT; event->mWaitStatus = false; } } status = event->mStatus; } mLock.lock(); return status; } Loading @@ -373,63 +382,71 @@ void AudioFlinger::ThreadBase::sendIoConfigEvent(int event, int param) // sendIoConfigEvent_l() must be called with ThreadBase::mLock held void AudioFlinger::ThreadBase::sendIoConfigEvent_l(int event, int param) { IoConfigEvent *ioEvent = new IoConfigEvent(event, param); mConfigEvents.add(static_cast<ConfigEvent *>(ioEvent)); ALOGV("sendIoConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param); mWaitWorkCV.signal(); sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, param); sendConfigEvent_l(configEvent); } // sendPrioConfigEvent_l() must be called with ThreadBase::mLock held void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio) { PrioConfigEvent *prioEvent = new PrioConfigEvent(pid, tid, prio); mConfigEvents.add(static_cast<ConfigEvent *>(prioEvent)); ALOGV("sendPrioConfigEvent_l() num events %d pid %d, tid %d prio %d", mConfigEvents.size(), pid, tid, prio); mWaitWorkCV.signal(); sp<ConfigEvent> configEvent = (ConfigEvent *)new PrioConfigEvent(pid, tid, prio); sendConfigEvent_l(configEvent); } void AudioFlinger::ThreadBase::processConfigEvents() // sendSetParameterConfigEvent_l() must be called with ThreadBase::mLock held status_t AudioFlinger::ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair) { Mutex::Autolock _l(mLock); processConfigEvents_l(); sp<ConfigEvent> configEvent = (ConfigEvent *)new SetParameterConfigEvent(keyValuePair); return sendConfigEvent_l(configEvent); } // post condition: mConfigEvents.isEmpty() void AudioFlinger::ThreadBase::processConfigEvents_l() void AudioFlinger::ThreadBase::processConfigEvents_l( const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients) { bool configChanged = false; while (!mConfigEvents.isEmpty()) { ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size()); ConfigEvent *event = mConfigEvents[0]; ALOGV("processConfigEvents_l() remaining events %d", mConfigEvents.size()); sp<ConfigEvent> event = mConfigEvents[0]; mConfigEvents.removeAt(0); // release mLock before locking AudioFlinger mLock: lock order is always // AudioFlinger then ThreadBase to avoid cross deadlock mLock.unlock(); switch (event->type()) { switch (event->mType) { case CFG_EVENT_PRIO: { PrioConfigEvent *prioEvent = static_cast<PrioConfigEvent *>(event); // FIXME Need to understand why this has be done asynchronously int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio(), PrioConfigEventData *data = (PrioConfigEventData *)event->mData.get(); // FIXME Need to understand why this has to be done asynchronously int err = requestPriority(data->mPid, data->mTid, data->mPrio, true /*asynchronous*/); if (err != 0) { ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", prioEvent->prio(), prioEvent->pid(), prioEvent->tid(), err); data->mPrio, data->mPid, data->mTid, err); } } break; case CFG_EVENT_IO: { IoConfigEvent *ioEvent = static_cast<IoConfigEvent *>(event); { Mutex::Autolock _l(mAudioFlinger->mLock); audioConfigChanged_l(ioEvent->event(), ioEvent->param()); IoConfigEventData *data = (IoConfigEventData *)event->mData.get(); audioConfigChanged_l(notificationClients, data->mEvent, data->mParam); } break; case CFG_EVENT_SET_PARAMETER: { SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get(); if (checkForNewParameter_l(data->mKeyValuePairs, event->mStatus)) { configChanged = true; } } break; default: ALOGE("processConfigEvents() unknown event type %d", event->type()); ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType); break; } delete event; mLock.lock(); { Mutex::Autolock _l(event->mLock); if (event->mWaitStatus) { event->mWaitStatus = false; event->mCond.signal(); } } ALOGV_IF(mConfigEvents.isEmpty(), "processConfigEvents_l() DONE thread %p", this); } if (configChanged) { cacheParameters_l(); } } Loading Loading @@ -502,18 +519,6 @@ void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args __u channelMaskToString(mChannelMask, mType != RECORD).string()); fdprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat)); fdprintf(fd, " Frame size: %zu\n", mFrameSize); fdprintf(fd, " Pending setParameters commands:"); size_t numParams = mNewParameters.size(); if (numParams) { fdprintf(fd, "\n Index Command"); for (size_t i = 0; i < numParams; ++i) { fdprintf(fd, "\n %02zu ", i); fdprintf(fd, mNewParameters[i]); } fdprintf(fd, "\n"); } else { fdprintf(fd, " none\n"); } fdprintf(fd, " Pending config events:"); size_t numConfig = mConfigEvents.size(); if (numConfig) { Loading Loading @@ -1634,7 +1639,10 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) } // audioConfigChanged_l() must be called with AudioFlinger::mLock held void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { void AudioFlinger::PlaybackThread::audioConfigChanged_l( const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients, int event, int param) { AudioSystem::OutputDescriptor desc; void *param2 = NULL; Loading @@ -1649,7 +1657,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { desc.format = mFormat; desc.frameCount = mNormalFrameCount; // FIXME see // AudioFlinger::frameCount(audio_io_handle_t) desc.latency = latency(); desc.latency = latency_l(); param2 = &desc; break; Loading @@ -1659,7 +1667,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { default: break; } mAudioFlinger->audioConfigChanged_l(event, mId, param2); mAudioFlinger->audioConfigChanged_l(notificationClients, event, mId, param2); } void AudioFlinger::PlaybackThread::writeCallback() Loading Loading @@ -2309,12 +2317,16 @@ bool AudioFlinger::PlaybackThread::threadLoop() Vector< sp<EffectChain> > effectChains; processConfigEvents(); DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients = mAudioFlinger->notificationClients(); { // scope for mLock Mutex::Autolock _l(mLock); processConfigEvents_l(notificationClients); notificationClients.clear(); if (logString != NULL) { mNBLogWriter->logTimestamp(); mNBLogWriter->log(logString); Loading @@ -2327,10 +2339,6 @@ bool AudioFlinger::PlaybackThread::threadLoop() mLatchQValid = true; } if (checkForNewParameters_l()) { cacheParameters_l(); } saveOutputTracks(); if (mSignalPending) { // A signal was raised while we were unlocked Loading Loading @@ -3535,15 +3543,16 @@ void AudioFlinger::MixerThread::deleteTrackName_l(int name) mAudioMixer->deleteTrackName(name); } // checkForNewParameters_l() must be called with ThreadBase::mLock held bool AudioFlinger::MixerThread::checkForNewParameters_l() // checkForNewParameter_l() must be called with ThreadBase::mLock held bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePair, status_t& status) { // if !&IDLE, holds the FastMixer state to restore after new parameters processed FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE; bool reconfig = false; while (!mNewParameters.isEmpty()) { status = NO_ERROR; // if !&IDLE, holds the FastMixer state to restore after new parameters processed FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE; if (mFastMixer != NULL) { FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); Loading @@ -3557,11 +3566,8 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() } } status_t status = NO_ERROR; String8 keyValuePair = mNewParameters[0]; AudioParameter param = AudioParameter(keyValuePair); int value; if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) { reconfig = true; } Loading Loading @@ -3650,15 +3656,6 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() } } mNewParameters.removeAt(0); mParamStatus = status; mParamCond.signal(); // wait for condition with time out in case the thread calling ThreadBase::setParameters() // already timed out waiting for the status and will never signal the condition. mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs); } if (!(previousCommand & FastMixerState::IDLE)) { ALOG_ASSERT(mFastMixer != NULL); FastMixerStateQueue *sq = mFastMixer->sq(); Loading Loading @@ -3946,17 +3943,16 @@ void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name __unused) { } // checkForNewParameters_l() must be called with ThreadBase::mLock held bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() // checkForNewParameter_l() must be called with ThreadBase::mLock held bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair, status_t& status) { bool reconfig = false; while (!mNewParameters.isEmpty()) { status_t status = NO_ERROR; String8 keyValuePair = mNewParameters[0]; status = NO_ERROR; AudioParameter param = AudioParameter(keyValuePair); int value; if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) { // forward device change to effects that have requested to be // aware of attached audio device. Loading Loading @@ -3993,14 +3989,6 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() } } mNewParameters.removeAt(0); mParamStatus = status; mParamCond.signal(); // wait for condition with time out in case the thread calling ThreadBase::setParameters() // already timed out waiting for the status and will never signal the condition. mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs); } return reconfig; } Loading Loading @@ -4707,12 +4695,14 @@ reacquire_wakelock: // activeTracks accumulates a copy of a subset of mActiveTracks Vector< sp<RecordTrack> > activeTracks; DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients = mAudioFlinger->notificationClients(); { // scope for mLock Mutex::Autolock _l(mLock); processConfigEvents_l(); // return value 'reconfig' is currently unused bool reconfig = checkForNewParameters_l(); processConfigEvents_l(notificationClients); notificationClients.clear(); // check exitPending here because checkForNewParameters_l() and // checkForNewParameters_l() can temporarily release mLock Loading Loading @@ -5487,19 +5477,19 @@ void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer( buffer->frameCount = 0; } bool AudioFlinger::RecordThread::checkForNewParameters_l() bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValuePair, status_t& status) { bool reconfig = false; while (!mNewParameters.isEmpty()) { status_t status = NO_ERROR; String8 keyValuePair = mNewParameters[0]; AudioParameter param = AudioParameter(keyValuePair); int value; status = NO_ERROR; audio_format_t reqFormat = mFormat; uint32_t samplingRate = mSampleRate; audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(mChannelCount); AudioParameter param = AudioParameter(keyValuePair); int value; // TODO Investigate when this code runs. Check with audio policy when a sample rate and // channel count change can be requested. Do we mandate the first client defines the // HAL sampling rate and channel count or do we allow changes on the fly? Loading Loading @@ -5599,14 +5589,6 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() } } mNewParameters.removeAt(0); mParamStatus = status; mParamCond.signal(); // wait for condition with time out in case the thread calling ThreadBase::setParameters() // already timed out waiting for the status and will never signal the condition. mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs); } return reconfig; } Loading @@ -5623,7 +5605,10 @@ String8 AudioFlinger::RecordThread::getParameters(const String8& keys) return out_s8; } void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param __unused) { void AudioFlinger::RecordThread::audioConfigChanged_l( const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients, int event, int param __unused) { AudioSystem::OutputDescriptor desc; const void *param2 = NULL; Loading @@ -5642,7 +5627,7 @@ void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param __unu default: break; } mAudioFlinger->audioConfigChanged_l(event, mId, param2); mAudioFlinger->audioConfigChanged_l(notificationClients, event, mId, param2); } void AudioFlinger::RecordThread::readInputParameters_l() Loading services/audioflinger/Threads.h +114 −57 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/audioflinger/AudioFlinger.cpp +14 −9 Original line number Diff line number Diff line Loading @@ -1195,11 +1195,16 @@ void AudioFlinger::removeNotificationClient(pid_t pid) } // audioConfigChanged_l() must be called with AudioFlinger::mLock held void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2) void AudioFlinger::audioConfigChanged_l( const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients, int event, audio_io_handle_t ioHandle, const void *param2) { size_t size = mNotificationClients.size(); size_t size = notificationClients.size(); for (size_t i = 0; i < size; i++) { mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle, notificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle, param2); } } Loading Loading @@ -1633,7 +1638,7 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, } // notify client processes of the new output creation thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); thread->audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_OPENED); // the first primary output opened designates the primary hw device if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) { Loading Loading @@ -1669,7 +1674,7 @@ audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1, thread->addOutputTrack(thread2); mPlaybackThreads.add(id, thread); // notify client processes of the new output creation thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); thread->audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_OPENED); return id; } Loading Loading @@ -1719,7 +1724,7 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output) } } } audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL); audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_CLOSED, output, NULL); } thread->exit(); // The thread entity (active unit of execution) is no longer running here, Loading Loading @@ -1899,7 +1904,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, } // notify client processes of the new input creation thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED); thread->audioConfigChanged_l(mNotificationClients, AudioSystem::INPUT_OPENED); return id; } Loading @@ -1924,7 +1929,7 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input) } ALOGV("closeInput() %d", input); audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, NULL); audioConfigChanged_l(mNotificationClients, AudioSystem::INPUT_CLOSED, input, NULL); mRecordThreads.removeItem(input); } thread->exit(); Loading
services/audioflinger/AudioFlinger.h +7 −2 Original line number Diff line number Diff line Loading @@ -454,7 +454,11 @@ private: // no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held float streamVolume_l(audio_stream_type_t stream) const { return mStreamTypes[stream].volume; } void audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2); void audioConfigChanged_l(const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients, int event, audio_io_handle_t ioHandle, const void *param2); // Allocate an audio_io_handle_t, session ID, effect ID, or audio_module_handle_t. // They all share the same ID space, but the namespaces are actually independent Loading @@ -479,7 +483,8 @@ private: void removeClient_l(pid_t pid); void removeNotificationClient(pid_t pid); DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients() { Mutex::Autolock _l(mLock); return mNotificationClients; } bool isNonOffloadableGlobalEffectEnabled_l(); void onNonOffloadableGlobalEffectEnable(); Loading
services/audioflinger/Threads.cpp +301 −316 Original line number Diff line number Diff line Loading @@ -97,8 +97,8 @@ static const nsecs_t kWarningThrottleNs = seconds(5); // RecordThread loop sleep time upon application overrun or audio HAL read error static const int kRecordThreadSleepUs = 5000; // maximum time to wait for setParameters to complete static const nsecs_t kSetParametersTimeoutNs = seconds(2); // maximum time to wait in sendConfigEvent_l() for a status to be received static const nsecs_t kConfigEventTimeoutNs = seconds(2); // minimum sleep time for the mixer thread loop when tracks are active but in underrun static const uint32_t kMinThreadSleepTimeUs = 5000; Loading Loading @@ -283,7 +283,6 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio // mSampleRate, mFrameCount, mChannelMask, mChannelCount, mFrameSize, mFormat, mBufferSize // are set by PlaybackThread::readOutputParameters_l() or // RecordThread::readInputParameters_l() mParamStatus(NO_ERROR), //FIXME: mStandby should be true here. Is this some kind of hack? mStandby(false), mOutDevice(outDevice), mInDevice(inDevice), mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), Loading @@ -295,12 +294,8 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio AudioFlinger::ThreadBase::~ThreadBase() { // mConfigEvents should be empty, but just in case it isn't, free the memory it owns for (size_t i = 0; i < mConfigEvents.size(); i++) { delete mConfigEvents[i]; } mConfigEvents.clear(); mParamCond.broadcast(); // do not lock the mutex in destructor releaseWakeLock_l(); if (mPowerManager != 0) { Loading Loading @@ -351,16 +346,30 @@ status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs) ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string()); Mutex::Autolock _l(mLock); mNewParameters.add(keyValuePairs); mWaitWorkCV.signal(); // wait condition with timeout in case the thread loop has exited // before the request could be processed if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) { status = mParamStatus; return sendSetParameterConfigEvent_l(keyValuePairs); } // sendConfigEvent_l() must be called with ThreadBase::mLock held // Can temporarily release the lock if waiting for a reply from processConfigEvents_l(). status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event) { status_t status = NO_ERROR; mConfigEvents.add(event); ALOGV("sendConfigEvent_l() num events %d event %d", mConfigEvents.size(), event->mType); mWaitWorkCV.signal(); } else { status = TIMED_OUT; mLock.unlock(); { Mutex::Autolock _l(event->mLock); while (event->mWaitStatus) { if (event->mCond.waitRelative(event->mLock, kConfigEventTimeoutNs) != NO_ERROR) { event->mStatus = TIMED_OUT; event->mWaitStatus = false; } } status = event->mStatus; } mLock.lock(); return status; } Loading @@ -373,63 +382,71 @@ void AudioFlinger::ThreadBase::sendIoConfigEvent(int event, int param) // sendIoConfigEvent_l() must be called with ThreadBase::mLock held void AudioFlinger::ThreadBase::sendIoConfigEvent_l(int event, int param) { IoConfigEvent *ioEvent = new IoConfigEvent(event, param); mConfigEvents.add(static_cast<ConfigEvent *>(ioEvent)); ALOGV("sendIoConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param); mWaitWorkCV.signal(); sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, param); sendConfigEvent_l(configEvent); } // sendPrioConfigEvent_l() must be called with ThreadBase::mLock held void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio) { PrioConfigEvent *prioEvent = new PrioConfigEvent(pid, tid, prio); mConfigEvents.add(static_cast<ConfigEvent *>(prioEvent)); ALOGV("sendPrioConfigEvent_l() num events %d pid %d, tid %d prio %d", mConfigEvents.size(), pid, tid, prio); mWaitWorkCV.signal(); sp<ConfigEvent> configEvent = (ConfigEvent *)new PrioConfigEvent(pid, tid, prio); sendConfigEvent_l(configEvent); } void AudioFlinger::ThreadBase::processConfigEvents() // sendSetParameterConfigEvent_l() must be called with ThreadBase::mLock held status_t AudioFlinger::ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair) { Mutex::Autolock _l(mLock); processConfigEvents_l(); sp<ConfigEvent> configEvent = (ConfigEvent *)new SetParameterConfigEvent(keyValuePair); return sendConfigEvent_l(configEvent); } // post condition: mConfigEvents.isEmpty() void AudioFlinger::ThreadBase::processConfigEvents_l() void AudioFlinger::ThreadBase::processConfigEvents_l( const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients) { bool configChanged = false; while (!mConfigEvents.isEmpty()) { ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size()); ConfigEvent *event = mConfigEvents[0]; ALOGV("processConfigEvents_l() remaining events %d", mConfigEvents.size()); sp<ConfigEvent> event = mConfigEvents[0]; mConfigEvents.removeAt(0); // release mLock before locking AudioFlinger mLock: lock order is always // AudioFlinger then ThreadBase to avoid cross deadlock mLock.unlock(); switch (event->type()) { switch (event->mType) { case CFG_EVENT_PRIO: { PrioConfigEvent *prioEvent = static_cast<PrioConfigEvent *>(event); // FIXME Need to understand why this has be done asynchronously int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio(), PrioConfigEventData *data = (PrioConfigEventData *)event->mData.get(); // FIXME Need to understand why this has to be done asynchronously int err = requestPriority(data->mPid, data->mTid, data->mPrio, true /*asynchronous*/); if (err != 0) { ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", prioEvent->prio(), prioEvent->pid(), prioEvent->tid(), err); data->mPrio, data->mPid, data->mTid, err); } } break; case CFG_EVENT_IO: { IoConfigEvent *ioEvent = static_cast<IoConfigEvent *>(event); { Mutex::Autolock _l(mAudioFlinger->mLock); audioConfigChanged_l(ioEvent->event(), ioEvent->param()); IoConfigEventData *data = (IoConfigEventData *)event->mData.get(); audioConfigChanged_l(notificationClients, data->mEvent, data->mParam); } break; case CFG_EVENT_SET_PARAMETER: { SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get(); if (checkForNewParameter_l(data->mKeyValuePairs, event->mStatus)) { configChanged = true; } } break; default: ALOGE("processConfigEvents() unknown event type %d", event->type()); ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType); break; } delete event; mLock.lock(); { Mutex::Autolock _l(event->mLock); if (event->mWaitStatus) { event->mWaitStatus = false; event->mCond.signal(); } } ALOGV_IF(mConfigEvents.isEmpty(), "processConfigEvents_l() DONE thread %p", this); } if (configChanged) { cacheParameters_l(); } } Loading Loading @@ -502,18 +519,6 @@ void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args __u channelMaskToString(mChannelMask, mType != RECORD).string()); fdprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat)); fdprintf(fd, " Frame size: %zu\n", mFrameSize); fdprintf(fd, " Pending setParameters commands:"); size_t numParams = mNewParameters.size(); if (numParams) { fdprintf(fd, "\n Index Command"); for (size_t i = 0; i < numParams; ++i) { fdprintf(fd, "\n %02zu ", i); fdprintf(fd, mNewParameters[i]); } fdprintf(fd, "\n"); } else { fdprintf(fd, " none\n"); } fdprintf(fd, " Pending config events:"); size_t numConfig = mConfigEvents.size(); if (numConfig) { Loading Loading @@ -1634,7 +1639,10 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) } // audioConfigChanged_l() must be called with AudioFlinger::mLock held void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { void AudioFlinger::PlaybackThread::audioConfigChanged_l( const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients, int event, int param) { AudioSystem::OutputDescriptor desc; void *param2 = NULL; Loading @@ -1649,7 +1657,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { desc.format = mFormat; desc.frameCount = mNormalFrameCount; // FIXME see // AudioFlinger::frameCount(audio_io_handle_t) desc.latency = latency(); desc.latency = latency_l(); param2 = &desc; break; Loading @@ -1659,7 +1667,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { default: break; } mAudioFlinger->audioConfigChanged_l(event, mId, param2); mAudioFlinger->audioConfigChanged_l(notificationClients, event, mId, param2); } void AudioFlinger::PlaybackThread::writeCallback() Loading Loading @@ -2309,12 +2317,16 @@ bool AudioFlinger::PlaybackThread::threadLoop() Vector< sp<EffectChain> > effectChains; processConfigEvents(); DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients = mAudioFlinger->notificationClients(); { // scope for mLock Mutex::Autolock _l(mLock); processConfigEvents_l(notificationClients); notificationClients.clear(); if (logString != NULL) { mNBLogWriter->logTimestamp(); mNBLogWriter->log(logString); Loading @@ -2327,10 +2339,6 @@ bool AudioFlinger::PlaybackThread::threadLoop() mLatchQValid = true; } if (checkForNewParameters_l()) { cacheParameters_l(); } saveOutputTracks(); if (mSignalPending) { // A signal was raised while we were unlocked Loading Loading @@ -3535,15 +3543,16 @@ void AudioFlinger::MixerThread::deleteTrackName_l(int name) mAudioMixer->deleteTrackName(name); } // checkForNewParameters_l() must be called with ThreadBase::mLock held bool AudioFlinger::MixerThread::checkForNewParameters_l() // checkForNewParameter_l() must be called with ThreadBase::mLock held bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePair, status_t& status) { // if !&IDLE, holds the FastMixer state to restore after new parameters processed FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE; bool reconfig = false; while (!mNewParameters.isEmpty()) { status = NO_ERROR; // if !&IDLE, holds the FastMixer state to restore after new parameters processed FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE; if (mFastMixer != NULL) { FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); Loading @@ -3557,11 +3566,8 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() } } status_t status = NO_ERROR; String8 keyValuePair = mNewParameters[0]; AudioParameter param = AudioParameter(keyValuePair); int value; if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) { reconfig = true; } Loading Loading @@ -3650,15 +3656,6 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() } } mNewParameters.removeAt(0); mParamStatus = status; mParamCond.signal(); // wait for condition with time out in case the thread calling ThreadBase::setParameters() // already timed out waiting for the status and will never signal the condition. mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs); } if (!(previousCommand & FastMixerState::IDLE)) { ALOG_ASSERT(mFastMixer != NULL); FastMixerStateQueue *sq = mFastMixer->sq(); Loading Loading @@ -3946,17 +3943,16 @@ void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name __unused) { } // checkForNewParameters_l() must be called with ThreadBase::mLock held bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() // checkForNewParameter_l() must be called with ThreadBase::mLock held bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair, status_t& status) { bool reconfig = false; while (!mNewParameters.isEmpty()) { status_t status = NO_ERROR; String8 keyValuePair = mNewParameters[0]; status = NO_ERROR; AudioParameter param = AudioParameter(keyValuePair); int value; if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) { // forward device change to effects that have requested to be // aware of attached audio device. Loading Loading @@ -3993,14 +3989,6 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() } } mNewParameters.removeAt(0); mParamStatus = status; mParamCond.signal(); // wait for condition with time out in case the thread calling ThreadBase::setParameters() // already timed out waiting for the status and will never signal the condition. mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs); } return reconfig; } Loading Loading @@ -4707,12 +4695,14 @@ reacquire_wakelock: // activeTracks accumulates a copy of a subset of mActiveTracks Vector< sp<RecordTrack> > activeTracks; DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients = mAudioFlinger->notificationClients(); { // scope for mLock Mutex::Autolock _l(mLock); processConfigEvents_l(); // return value 'reconfig' is currently unused bool reconfig = checkForNewParameters_l(); processConfigEvents_l(notificationClients); notificationClients.clear(); // check exitPending here because checkForNewParameters_l() and // checkForNewParameters_l() can temporarily release mLock Loading Loading @@ -5487,19 +5477,19 @@ void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer( buffer->frameCount = 0; } bool AudioFlinger::RecordThread::checkForNewParameters_l() bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValuePair, status_t& status) { bool reconfig = false; while (!mNewParameters.isEmpty()) { status_t status = NO_ERROR; String8 keyValuePair = mNewParameters[0]; AudioParameter param = AudioParameter(keyValuePair); int value; status = NO_ERROR; audio_format_t reqFormat = mFormat; uint32_t samplingRate = mSampleRate; audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(mChannelCount); AudioParameter param = AudioParameter(keyValuePair); int value; // TODO Investigate when this code runs. Check with audio policy when a sample rate and // channel count change can be requested. Do we mandate the first client defines the // HAL sampling rate and channel count or do we allow changes on the fly? Loading Loading @@ -5599,14 +5589,6 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() } } mNewParameters.removeAt(0); mParamStatus = status; mParamCond.signal(); // wait for condition with time out in case the thread calling ThreadBase::setParameters() // already timed out waiting for the status and will never signal the condition. mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs); } return reconfig; } Loading @@ -5623,7 +5605,10 @@ String8 AudioFlinger::RecordThread::getParameters(const String8& keys) return out_s8; } void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param __unused) { void AudioFlinger::RecordThread::audioConfigChanged_l( const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients, int event, int param __unused) { AudioSystem::OutputDescriptor desc; const void *param2 = NULL; Loading @@ -5642,7 +5627,7 @@ void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param __unu default: break; } mAudioFlinger->audioConfigChanged_l(event, mId, param2); mAudioFlinger->audioConfigChanged_l(notificationClients, event, mId, param2); } void AudioFlinger::RecordThread::readInputParameters_l() Loading
services/audioflinger/Threads.h +114 −57 File changed.Preview size limit exceeded, changes collapsed. Show changes