diff options
Diffstat (limited to 'services/audioflinger')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 34 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 13 | ||||
-rw-r--r-- | services/audioflinger/AudioMixer.cpp | 111 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 190 | ||||
-rw-r--r-- | services/audioflinger/Threads.h | 31 |
5 files changed, 260 insertions, 119 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 93b1642..52fce34 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -181,7 +181,8 @@ AudioFlinger::AudioFlinger() mIsLowRamDevice(true), mIsDeviceTypeKnown(false), mGlobalEffectEnableTime(0), - mPrimaryOutputSampleRate(0) + mPrimaryOutputSampleRate(0), + mSystemReady(false) { getpid_cached = getpid(); char value[PROPERTY_VALUE_MAX]; @@ -1722,6 +1723,26 @@ audio_hw_sync_t AudioFlinger::getAudioHwSyncForSession(audio_session_t sessionId return (audio_hw_sync_t)value; } +status_t AudioFlinger::systemReady() +{ + Mutex::Autolock _l(mLock); + ALOGI("%s", __FUNCTION__); + if (mSystemReady) { + ALOGW("%s called twice", __FUNCTION__); + return NO_ERROR; + } + mSystemReady = true; + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + ThreadBase *thread = (ThreadBase *)mPlaybackThreads.valueAt(i).get(); + thread->systemReady(); + } + for (size_t i = 0; i < mRecordThreads.size(); i++) { + ThreadBase *thread = (ThreadBase *)mRecordThreads.valueAt(i).get(); + thread->systemReady(); + } + return NO_ERROR; +} + // setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId) { @@ -1794,15 +1815,15 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_ PlaybackThread *thread; if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { - thread = new OffloadThread(this, outputStream, *output, devices); + thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread); } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || !isValidPcmSinkFormat(config->format) || !isValidPcmSinkChannelMask(config->channel_mask)) { - thread = new DirectOutputThread(this, outputStream, *output, devices); + thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created direct output: ID %d thread %p", *output, thread); } else { - thread = new MixerThread(this, outputStream, *output, devices); + thread = new MixerThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created mixer output: ID %d thread %p", *output, thread); } mPlaybackThreads.add(*output, thread); @@ -1873,7 +1894,7 @@ audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1, } audio_io_handle_t id = nextUniqueId(); - DuplicatingThread *thread = new DuplicatingThread(this, thread1, id); + DuplicatingThread *thread = new DuplicatingThread(this, thread1, id, mSystemReady); thread->addOutputTrack(thread2); mPlaybackThreads.add(id, thread); // notify client processes of the new output creation @@ -2120,7 +2141,8 @@ sp<AudioFlinger::RecordThread> AudioFlinger::openInput_l(audio_module_handle_t m inputStream, *input, primaryOutputDevice_l(), - devices + devices, + mSystemReady #ifdef TEE_SINK , teeSink #endif diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 51b2610..d087ced 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -257,6 +257,9 @@ public: /* Get the HW synchronization source used for an audio session */ virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId); + /* Indicate JAVA services are ready (scheduling, power management ...) */ + virtual status_t systemReady(); + virtual status_t onTransact( uint32_t code, const Parcel& data, @@ -356,6 +359,15 @@ private: // check that channelMask is the "canonical" one we expect for the channelCount. return channelMask == audio_channel_out_mask_from_count(channelCount); } + case AUDIO_CHANNEL_REPRESENTATION_INDEX: + if (kEnableExtendedChannels) { + const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask); + if (channelCount >= FCC_2 // mono is not supported at this time + && channelCount <= AudioMixer::MAX_NUM_CHANNELS) { + return true; + } + } + return false; default: return false; } @@ -752,6 +764,7 @@ private: uint32_t mPrimaryOutputSampleRate; // sample rate of the primary output, or zero if none // protected by mHardwareLock + bool mSystemReady; }; #undef INCLUDING_FROM_AUDIOFLINGER_H diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index 586c737..01efc53 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -66,6 +66,13 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) #endif +// TODO: Move these macro/inlines to a header file. +template <typename T> +static inline +T max(const T& x, const T& y) { + return x > y ? x : y; +} + // Set kUseNewMixer to true to use the new mixer engine always. Otherwise the // original code will be used for stereo sinks, the new mixer for multichannel. static const bool kUseNewMixer = true; @@ -499,41 +506,99 @@ void AudioMixer::disable(int name) static inline bool setVolumeRampVariables(float newVolume, int32_t ramp, int16_t *pIntSetVolume, int32_t *pIntPrevVolume, int32_t *pIntVolumeInc, float *pSetVolume, float *pPrevVolume, float *pVolumeInc) { + // check floating point volume to see if it is identical to the previously + // set volume. + // We do not use a tolerance here (and reject changes too small) + // as it may be confusing to use a different value than the one set. + // If the resulting volume is too small to ramp, it is a direct set of the volume. if (newVolume == *pSetVolume) { return false; } - /* set the floating point volume variables */ - if (ramp != 0) { - *pVolumeInc = (newVolume - *pSetVolume) / ramp; - *pPrevVolume = *pSetVolume; + if (newVolume < 0) { + newVolume = 0; // should not have negative volumes } else { - *pVolumeInc = 0; - *pPrevVolume = newVolume; + switch (fpclassify(newVolume)) { + case FP_SUBNORMAL: + case FP_NAN: + newVolume = 0; + break; + case FP_ZERO: + break; // zero volume is fine + case FP_INFINITE: + // Infinite volume could be handled consistently since + // floating point math saturates at infinities, + // but we limit volume to unity gain float. + // ramp = 0; break; + // + newVolume = AudioMixer::UNITY_GAIN_FLOAT; + break; + case FP_NORMAL: + default: + // Floating point does not have problems with overflow wrap + // that integer has. However, we limit the volume to + // unity gain here. + // TODO: Revisit the volume limitation and perhaps parameterize. + if (newVolume > AudioMixer::UNITY_GAIN_FLOAT) { + newVolume = AudioMixer::UNITY_GAIN_FLOAT; + } + break; + } + } + + // set floating point volume ramp + if (ramp != 0) { + // when the ramp completes, *pPrevVolume is set to *pSetVolume, so there + // is no computational mismatch; hence equality is checked here. + ALOGD_IF(*pPrevVolume != *pSetVolume, "previous float ramp hasn't finished," + " prev:%f set_to:%f", *pPrevVolume, *pSetVolume); + const float inc = (newVolume - *pPrevVolume) / ramp; // could be inf, nan, subnormal + const float maxv = max(newVolume, *pPrevVolume); // could be inf, cannot be nan, subnormal + + if (isnormal(inc) // inc must be a normal number (no subnormals, infinite, nan) + && maxv + inc != maxv) { // inc must make forward progress + *pVolumeInc = inc; + // ramp is set now. + // Note: if newVolume is 0, then near the end of the ramp, + // it may be possible that the ramped volume may be subnormal or + // temporarily negative by a small amount or subnormal due to floating + // point inaccuracies. + } else { + ramp = 0; // ramp not allowed + } } - *pSetVolume = newVolume; - /* set the legacy integer volume variables */ - int32_t intVolume = newVolume * AudioMixer::UNITY_GAIN_INT; - if (intVolume > AudioMixer::UNITY_GAIN_INT) { - intVolume = AudioMixer::UNITY_GAIN_INT; - } else if (intVolume < 0) { - ALOGE("negative volume %.7g", newVolume); - intVolume = 0; // should never happen, but for safety check. + // compute and check integer volume, no need to check negative values + // The integer volume is limited to "unity_gain" to avoid wrapping and other + // audio artifacts, so it never reaches the range limit of U4.28. + // We safely use signed 16 and 32 bit integers here. + const float scaledVolume = newVolume * AudioMixer::UNITY_GAIN_INT; // not neg, subnormal, nan + const int32_t intVolume = (scaledVolume >= (float)AudioMixer::UNITY_GAIN_INT) ? + AudioMixer::UNITY_GAIN_INT : (int32_t)scaledVolume; + + // set integer volume ramp + if (ramp != 0) { + // integer volume is U4.12 (to use 16 bit multiplies), but ramping uses U4.28. + // when the ramp completes, *pIntPrevVolume is set to *pIntSetVolume << 16, so there + // is no computational mismatch; hence equality is checked here. + ALOGD_IF(*pIntPrevVolume != *pIntSetVolume << 16, "previous int ramp hasn't finished," + " prev:%d set_to:%d", *pIntPrevVolume, *pIntSetVolume << 16); + const int32_t inc = ((intVolume << 16) - *pIntPrevVolume) / ramp; + + if (inc != 0) { // inc must make forward progress + *pIntVolumeInc = inc; + } else { + ramp = 0; // ramp not allowed + } } - if (intVolume == *pIntSetVolume) { - *pIntVolumeInc = 0; - /* TODO: integer/float workaround: ignore floating volume ramp */ + + // if no ramp, or ramp not allowed, then clear float and integer increments + if (ramp == 0) { *pVolumeInc = 0; *pPrevVolume = newVolume; - return true; - } - if (ramp != 0) { - *pIntVolumeInc = ((intVolume - *pIntSetVolume) << 16) / ramp; - *pIntPrevVolume = (*pIntVolumeInc == 0 ? intVolume : *pIntSetVolume) << 16; - } else { *pIntVolumeInc = 0; *pIntPrevVolume = intVolume << 16; } + *pSetVolume = newVolume; *pIntSetVolume = intVolume; return true; } diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index d9b4249..721f6af 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -487,7 +487,7 @@ const char *sourceToString(audio_source_t source) } AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, - audio_devices_t outDevice, audio_devices_t inDevice, type_t type) + audio_devices_t outDevice, audio_devices_t inDevice, type_t type, bool systemReady) : Thread(false /*canCallJava*/), mType(type), mAudioFlinger(audioFlinger), @@ -498,7 +498,8 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio mStandby(false), mOutDevice(outDevice), mInDevice(inDevice), mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), // mName will be set by concrete (non-virtual) subclass - mDeathRecipient(new PMDeathRecipient(this)) + mDeathRecipient(new PMDeathRecipient(this)), + mSystemReady(systemReady) { memset(&mPatch, 0, sizeof(struct audio_patch)); } @@ -567,6 +568,11 @@ status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event) { status_t status = NO_ERROR; + if (event->mRequiresSystemReady && !mSystemReady) { + event->mWaitStatus = false; + mPendingConfigEvents.add(event); + return status; + } mConfigEvents.add(event); ALOGV("sendConfigEvent_l() num events %d event %d", mConfigEvents.size(), event->mType); mWaitWorkCV.signal(); @@ -598,6 +604,12 @@ void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event) sendConfigEvent_l(configEvent); } +void AudioFlinger::ThreadBase::sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio) +{ + Mutex::Autolock _l(mLock); + sendPrioConfigEvent_l(pid, tid, prio); +} + // sendPrioConfigEvent_l() must be called with ThreadBase::mLock held void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio) { @@ -697,49 +709,62 @@ void AudioFlinger::ThreadBase::processConfigEvents_l() String8 channelMaskToString(audio_channel_mask_t mask, bool output) { String8 s; - if (output) { - if (mask & AUDIO_CHANNEL_OUT_FRONT_LEFT) s.append("front-left, "); - if (mask & AUDIO_CHANNEL_OUT_FRONT_RIGHT) s.append("front-right, "); - if (mask & AUDIO_CHANNEL_OUT_FRONT_CENTER) s.append("front-center, "); - if (mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY) s.append("low freq, "); - if (mask & AUDIO_CHANNEL_OUT_BACK_LEFT) s.append("back-left, "); - if (mask & AUDIO_CHANNEL_OUT_BACK_RIGHT) s.append("back-right, "); - if (mask & AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER) s.append("front-left-of-center, "); - if (mask & AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER) s.append("front-right-of-center, "); - if (mask & AUDIO_CHANNEL_OUT_BACK_CENTER) s.append("back-center, "); - if (mask & AUDIO_CHANNEL_OUT_SIDE_LEFT) s.append("side-left, "); - if (mask & AUDIO_CHANNEL_OUT_SIDE_RIGHT) s.append("side-right, "); - if (mask & AUDIO_CHANNEL_OUT_TOP_CENTER) s.append("top-center ,"); - if (mask & AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT) s.append("top-front-left, "); - if (mask & AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER) s.append("top-front-center, "); - if (mask & AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT) s.append("top-front-right, "); - if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_LEFT) s.append("top-back-left, "); - if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_CENTER) s.append("top-back-center, " ); - if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT) s.append("top-back-right, " ); - if (mask & ~AUDIO_CHANNEL_OUT_ALL) s.append("unknown, "); - } else { - if (mask & AUDIO_CHANNEL_IN_LEFT) s.append("left, "); - if (mask & AUDIO_CHANNEL_IN_RIGHT) s.append("right, "); - if (mask & AUDIO_CHANNEL_IN_FRONT) s.append("front, "); - if (mask & AUDIO_CHANNEL_IN_BACK) s.append("back, "); - if (mask & AUDIO_CHANNEL_IN_LEFT_PROCESSED) s.append("left-processed, "); - if (mask & AUDIO_CHANNEL_IN_RIGHT_PROCESSED) s.append("right-processed, "); - if (mask & AUDIO_CHANNEL_IN_FRONT_PROCESSED) s.append("front-processed, "); - if (mask & AUDIO_CHANNEL_IN_BACK_PROCESSED) s.append("back-processed, "); - if (mask & AUDIO_CHANNEL_IN_PRESSURE) s.append("pressure, "); - if (mask & AUDIO_CHANNEL_IN_X_AXIS) s.append("X, "); - if (mask & AUDIO_CHANNEL_IN_Y_AXIS) s.append("Y, "); - if (mask & AUDIO_CHANNEL_IN_Z_AXIS) s.append("Z, "); - if (mask & AUDIO_CHANNEL_IN_VOICE_UPLINK) s.append("voice-uplink, "); - if (mask & AUDIO_CHANNEL_IN_VOICE_DNLINK) s.append("voice-dnlink, "); - if (mask & ~AUDIO_CHANNEL_IN_ALL) s.append("unknown, "); - } - int len = s.length(); - if (s.length() > 2) { - char *str = s.lockBuffer(len); - s.unlockBuffer(len - 2); - } - return s; + const audio_channel_representation_t representation = audio_channel_mask_get_representation(mask); + + switch (representation) { + case AUDIO_CHANNEL_REPRESENTATION_POSITION: { + if (output) { + if (mask & AUDIO_CHANNEL_OUT_FRONT_LEFT) s.append("front-left, "); + if (mask & AUDIO_CHANNEL_OUT_FRONT_RIGHT) s.append("front-right, "); + if (mask & AUDIO_CHANNEL_OUT_FRONT_CENTER) s.append("front-center, "); + if (mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY) s.append("low freq, "); + if (mask & AUDIO_CHANNEL_OUT_BACK_LEFT) s.append("back-left, "); + if (mask & AUDIO_CHANNEL_OUT_BACK_RIGHT) s.append("back-right, "); + if (mask & AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER) s.append("front-left-of-center, "); + if (mask & AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER) s.append("front-right-of-center, "); + if (mask & AUDIO_CHANNEL_OUT_BACK_CENTER) s.append("back-center, "); + if (mask & AUDIO_CHANNEL_OUT_SIDE_LEFT) s.append("side-left, "); + if (mask & AUDIO_CHANNEL_OUT_SIDE_RIGHT) s.append("side-right, "); + if (mask & AUDIO_CHANNEL_OUT_TOP_CENTER) s.append("top-center ,"); + if (mask & AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT) s.append("top-front-left, "); + if (mask & AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER) s.append("top-front-center, "); + if (mask & AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT) s.append("top-front-right, "); + if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_LEFT) s.append("top-back-left, "); + if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_CENTER) s.append("top-back-center, " ); + if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT) s.append("top-back-right, " ); + if (mask & ~AUDIO_CHANNEL_OUT_ALL) s.append("unknown, "); + } else { + if (mask & AUDIO_CHANNEL_IN_LEFT) s.append("left, "); + if (mask & AUDIO_CHANNEL_IN_RIGHT) s.append("right, "); + if (mask & AUDIO_CHANNEL_IN_FRONT) s.append("front, "); + if (mask & AUDIO_CHANNEL_IN_BACK) s.append("back, "); + if (mask & AUDIO_CHANNEL_IN_LEFT_PROCESSED) s.append("left-processed, "); + if (mask & AUDIO_CHANNEL_IN_RIGHT_PROCESSED) s.append("right-processed, "); + if (mask & AUDIO_CHANNEL_IN_FRONT_PROCESSED) s.append("front-processed, "); + if (mask & AUDIO_CHANNEL_IN_BACK_PROCESSED) s.append("back-processed, "); + if (mask & AUDIO_CHANNEL_IN_PRESSURE) s.append("pressure, "); + if (mask & AUDIO_CHANNEL_IN_X_AXIS) s.append("X, "); + if (mask & AUDIO_CHANNEL_IN_Y_AXIS) s.append("Y, "); + if (mask & AUDIO_CHANNEL_IN_Z_AXIS) s.append("Z, "); + if (mask & AUDIO_CHANNEL_IN_VOICE_UPLINK) s.append("voice-uplink, "); + if (mask & AUDIO_CHANNEL_IN_VOICE_DNLINK) s.append("voice-dnlink, "); + if (mask & ~AUDIO_CHANNEL_IN_ALL) s.append("unknown, "); + } + const int len = s.length(); + if (len > 2) { + char *str = s.lockBuffer(len); // needed? + s.unlockBuffer(len - 2); // remove trailing ", " + } + return s; + } + case AUDIO_CHANNEL_REPRESENTATION_INDEX: + s.appendFormat("index mask, bits:%#x", audio_channel_mask_get_bits(mask)); + return s; + default: + s.appendFormat("unknown mask, representation:%d bits:%#x", + representation, audio_channel_mask_get_bits(mask)); + return s; + } } void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args __unused) @@ -880,8 +905,7 @@ void AudioFlinger::ThreadBase::updateWakeLockUids(const SortedVector<int> &uids) } void AudioFlinger::ThreadBase::getPowerManager_l() { - - if (mPowerManager == 0) { + if (mSystemReady && mPowerManager == 0) { // use checkService() to avoid blocking if power service is not up yet sp<IBinder> binder = defaultServiceManager()->checkService(String16("power")); @@ -895,7 +919,6 @@ void AudioFlinger::ThreadBase::getPowerManager_l() { } void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<int> &uids) { - getPowerManager_l(); if (mWakeLockToken == NULL) { ALOGE("no wake lock to update!"); @@ -1337,6 +1360,20 @@ void AudioFlinger::ThreadBase::getAudioPortConfig(struct audio_port_config *conf AUDIO_PORT_CONFIG_FORMAT; } +void AudioFlinger::ThreadBase::systemReady() +{ + Mutex::Autolock _l(mLock); + if (mSystemReady) { + return; + } + mSystemReady = true; + + for (size_t i = 0; i < mPendingConfigEvents.size(); i++) { + sendConfigEvent_l(mPendingConfigEvents.editItemAt(i)); + } + mPendingConfigEvents.clear(); +} + // ---------------------------------------------------------------------------- // Playback @@ -1346,8 +1383,9 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, - type_t type) - : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type), + type_t type, + bool systemReady) + : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady), mNormalFrameCount(0), mSinkBuffer(NULL), mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision), mMixerBuffer(NULL), @@ -1572,10 +1610,12 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac ) && // PCM data audio_is_linear_pcm(format) && - // identical channel mask to sink, or mono in and stereo sink + // TODO: extract as a data library function that checks that a computationally + // expensive downmixer is not required: isFastOutputChannelConversion() (channelMask == mChannelMask || - (channelMask == AUDIO_CHANNEL_OUT_MONO && - mChannelMask == AUDIO_CHANNEL_OUT_STEREO)) && + mChannelMask != AUDIO_CHANNEL_OUT_STEREO || + (channelMask == AUDIO_CHANNEL_OUT_MONO + /* && mChannelMask == AUDIO_CHANNEL_OUT_STEREO */)) && // hardware sample rate (sampleRate == mSampleRate) && // normal mixer has an associated fast mixer @@ -3118,8 +3158,8 @@ void AudioFlinger::PlaybackThread::getAudioPortConfig(struct audio_port_config * // ---------------------------------------------------------------------------- AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, audio_devices_t device, type_t type) - : PlaybackThread(audioFlinger, output, id, device, type), + audio_io_handle_t id, audio_devices_t device, bool systemReady, type_t type) + : PlaybackThread(audioFlinger, output, id, device, type, systemReady), // mAudioMixer below // mFastMixer below mFastMixerFutex(0) @@ -3252,11 +3292,7 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud // start the fast mixer mFastMixer->run("FastMixer", PRIORITY_URGENT_AUDIO); pid_t tid = mFastMixer->getTid(); - int err = requestPriority(getpid_cached, tid, kPriorityFastMixer); - if (err != 0) { - ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", - kPriorityFastMixer, getpid_cached, tid, err); - } + sendPrioConfigEvent(getpid_cached, tid, kPriorityFastMixer); #ifdef AUDIO_WATCHDOG // create and start the watchdog @@ -3264,11 +3300,7 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud mAudioWatchdog->setDump(&mAudioWatchdogDump); mAudioWatchdog->run("AudioWatchdog", PRIORITY_URGENT_AUDIO); tid = mAudioWatchdog->getTid(); - err = requestPriority(getpid_cached, tid, kPriorityFastMixer); - if (err != 0) { - ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", - kPriorityFastMixer, getpid_cached, tid, err); - } + sendPrioConfigEvent(getpid_cached, tid, kPriorityFastMixer); #endif } @@ -4294,16 +4326,16 @@ void AudioFlinger::MixerThread::cacheParameters_l() // ---------------------------------------------------------------------------- AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, - AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device) - : PlaybackThread(audioFlinger, output, id, device, DIRECT) + AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady) + : PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady) // mLeftVolFloat, mRightVolFloat { } AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, audio_io_handle_t id, uint32_t device, - ThreadBase::type_t type) - : PlaybackThread(audioFlinger, output, id, device, type) + ThreadBase::type_t type, bool systemReady) + : PlaybackThread(audioFlinger, output, id, device, type, systemReady) // mLeftVolFloat, mRightVolFloat { } @@ -4832,8 +4864,8 @@ void AudioFlinger::AsyncCallbackThread::resetDraining() // ---------------------------------------------------------------------------- AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger, - AudioStreamOut* output, audio_io_handle_t id, uint32_t device) - : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD), + AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady) + : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady), mPausedBytesRemaining(0) { //FIXME: mStandby should be set to true by ThreadBase constructor @@ -5110,9 +5142,9 @@ void AudioFlinger::OffloadThread::onAddNewTrack_l() // ---------------------------------------------------------------------------- AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, - AudioFlinger::MixerThread* mainThread, audio_io_handle_t id) + AudioFlinger::MixerThread* mainThread, audio_io_handle_t id, bool systemReady) : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->outDevice(), - DUPLICATING), + systemReady, DUPLICATING), mWaitTimeMs(UINT_MAX) { addOutputTrack(mainThread); @@ -5292,12 +5324,13 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, audio_io_handle_t id, audio_devices_t outDevice, - audio_devices_t inDevice + audio_devices_t inDevice, + bool systemReady #ifdef TEE_SINK , const sp<NBAIO_Sink>& teeSink #endif ) : - ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD), + ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady), mInput(input), mActiveTracksGen(0), mRsmpInBuffer(NULL), // mRsmpInFrames and mRsmpInFramesP2 are set by readInputParameters_l() mRsmpInRear(0) @@ -5416,12 +5449,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, // start the fast capture mFastCapture->run("FastCapture", ANDROID_PRIORITY_URGENT_AUDIO); pid_t tid = mFastCapture->getTid(); - int err = requestPriority(getpid_cached, tid, kPriorityFastMixer); - if (err != 0) { - ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", - kPriorityFastCapture, getpid_cached, tid, err); - } - + sendPrioConfigEvent(getpid_cached, tid, kPriorityFastMixer); #ifdef AUDIO_WATCHDOG // FIXME #endif diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 37bacae..aa20525 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -35,7 +35,8 @@ public: static const char *threadTypeToString(type_t type); ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, - audio_devices_t outDevice, audio_devices_t inDevice, type_t type); + audio_devices_t outDevice, audio_devices_t inDevice, type_t type, + bool systemReady); virtual ~ThreadBase(); virtual status_t readyToRun(); @@ -92,10 +93,13 @@ public: Condition mCond; // condition for status return status_t mStatus; // status communicated to sender bool mWaitStatus; // true if sender is waiting for status + bool mRequiresSystemReady; // true if must wait for system ready to enter event queue sp<ConfigEventData> mData; // event specific parameter data protected: - ConfigEvent(int type) : mType(type), mStatus(NO_ERROR), mWaitStatus(false), mData(NULL) {} + ConfigEvent(int type, bool requiresSystemReady = false) : + mType(type), mStatus(NO_ERROR), mWaitStatus(false), + mRequiresSystemReady(requiresSystemReady), mData(NULL) {} }; class IoConfigEventData : public ConfigEventData { @@ -136,7 +140,7 @@ public: class PrioConfigEvent : public ConfigEvent { public: PrioConfigEvent(pid_t pid, pid_t tid, int32_t prio) : - ConfigEvent(CFG_EVENT_PRIO) { + ConfigEvent(CFG_EVENT_PRIO, true) { mData = new PrioConfigEventData(pid, tid, prio); } virtual ~PrioConfigEvent() {} @@ -258,6 +262,7 @@ public: status_t sendConfigEvent_l(sp<ConfigEvent>& event); void sendIoConfigEvent(audio_io_config_event event); void sendIoConfigEvent_l(audio_io_config_event event); + void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio); void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio); status_t sendSetParameterConfigEvent_l(const String8& keyValuePair); status_t sendCreateAudioPatchConfigEvent(const struct audio_patch *patch, @@ -359,6 +364,8 @@ public: virtual sp<IMemory> pipeMemory() const { return 0; } + void systemReady(); + mutable Mutex mLock; protected: @@ -418,6 +425,7 @@ protected: size_t mBufferSize; // HAL buffer size for read() or write() Vector< sp<ConfigEvent> > mConfigEvents; + Vector< sp<ConfigEvent> > mPendingConfigEvents; // events awaiting system ready // 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() @@ -445,6 +453,7 @@ protected: mSuspendedSessions; static const size_t kLogSize = 4 * 1024; sp<NBLog::Writer> mNBLogWriter; + bool mSystemReady; }; // --- PlaybackThread --- @@ -470,7 +479,7 @@ public: static const int8_t kMaxTrackRetriesOffload = 20; PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, audio_devices_t device, type_t type); + audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady); virtual ~PlaybackThread(); void dump(int fd, const Vector<String16>& args); @@ -842,6 +851,7 @@ public: AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, + bool systemReady, type_t type = MIXER); virtual ~MixerThread(); @@ -903,7 +913,7 @@ class DirectOutputThread : public PlaybackThread { public: DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, audio_devices_t device); + audio_io_handle_t id, audio_devices_t device, bool systemReady); virtual ~DirectOutputThread(); // Thread virtuals @@ -933,7 +943,8 @@ protected: float mRightVolFloat; DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, uint32_t device, ThreadBase::type_t type); + audio_io_handle_t id, uint32_t device, ThreadBase::type_t type, + bool systemReady); void processVolume_l(Track *track, bool lastTrack); // prepareTracks_l() tells threadLoop_mix() the name of the single active track @@ -946,7 +957,7 @@ class OffloadThread : public DirectOutputThread { public: OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, - audio_io_handle_t id, uint32_t device); + audio_io_handle_t id, uint32_t device, bool systemReady); virtual ~OffloadThread() {}; virtual void flushHw_l(); @@ -1001,7 +1012,7 @@ private: class DuplicatingThread : public MixerThread { public: DuplicatingThread(const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, - audio_io_handle_t id); + audio_io_handle_t id, bool systemReady); virtual ~DuplicatingThread(); // Thread virtuals @@ -1177,7 +1188,8 @@ public: AudioStreamIn *input, audio_io_handle_t id, audio_devices_t outDevice, - audio_devices_t inDevice + audio_devices_t inDevice, + bool systemReady #ifdef TEE_SINK , const sp<NBAIO_Sink>& teeSink #endif @@ -1294,6 +1306,7 @@ private: // one-time initialization, no locks required sp<FastCapture> mFastCapture; // non-0 if there is also // a fast capture + // FIXME audio watchdog thread // contents are not guaranteed to be consistent, no locks required |