diff options
Diffstat (limited to 'services/audioflinger/Threads.cpp')
-rw-r--r-- | services/audioflinger/Threads.cpp | 126 |
1 files changed, 97 insertions, 29 deletions
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index e0b664b..c3aafd9 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -910,6 +910,15 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( goto Exit; } + // Reject any effect on multichannel sinks. + // TODO: fix both format and multichannel issues with effects. + if (mChannelCount != FCC_2) { + ALOGW("createEffect_l() Cannot add effect %s for multichannel(%d) thread", + desc->name, mChannelCount); + lStatus = BAD_VALUE; + goto Exit; + } + // Allow global effects only on offloaded and mixer threads if (sessionId == AUDIO_SESSION_OUTPUT_MIX) { switch (mType) { @@ -1146,6 +1155,18 @@ void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect, } } +void AudioFlinger::ThreadBase::getAudioPortConfig(struct audio_port_config *config) +{ + config->type = AUDIO_PORT_TYPE_MIX; + config->ext.mix.handle = mId; + config->sample_rate = mSampleRate; + config->format = mFormat; + config->channel_mask = mChannelMask; + config->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| + AUDIO_PORT_CONFIG_FORMAT; +} + + // ---------------------------------------------------------------------------- // Playback // ---------------------------------------------------------------------------- @@ -1376,9 +1397,10 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac ) && // PCM data audio_is_linear_pcm(format) && - // mono or stereo - ( (channelMask == AUDIO_CHANNEL_OUT_MONO) || - (channelMask == AUDIO_CHANNEL_OUT_STEREO) ) && + // identical channel mask to sink, or mono in and stereo sink + (channelMask == mChannelMask || + (channelMask == AUDIO_CHANNEL_OUT_MONO && + mChannelMask == AUDIO_CHANNEL_OUT_STEREO)) && // hardware sample rate (sampleRate == mSampleRate) && // normal mixer has an associated fast mixer @@ -1482,7 +1504,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac uint32_t strategy = AudioSystem::getStrategyForStream(streamType); for (size_t i = 0; i < mTracks.size(); ++i) { sp<Track> t = mTracks[i]; - if (t != 0 && !t->isOutputTrack()) { + if (t != 0 && t->isExternalTrack()) { uint32_t actual = AudioSystem::getStrategyForStream(t->streamType()); if (sessionId == t->sessionId() && strategy != actual) { ALOGE("createTrack_l() mismatched strategy; expected %u but found %u", @@ -1495,7 +1517,8 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac if (!isTimed) { track = new Track(this, client, streamType, sampleRate, format, - channelMask, frameCount, sharedBuffer, sessionId, uid, *flags); + channelMask, frameCount, NULL, sharedBuffer, + sessionId, uid, *flags, TrackBase::TYPE_DEFAULT); } else { track = TimedTrack::create(this, client, streamType, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId, uid); @@ -1608,7 +1631,7 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) // the track is newly added, make sure it fills up all its // buffers before playing. This is to ensure the client will // effectively get the latency it requested. - if (!track->isOutputTrack()) { + if (track->isExternalTrack()) { TrackBase::track_state state = track->mState; mLock.unlock(); status = AudioSystem::startOutput(mId, track->streamType(), track->sessionId()); @@ -1801,9 +1824,10 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l() if (!audio_is_output_channel(mChannelMask)) { LOG_ALWAYS_FATAL("HAL channel mask %#x not valid for output", mChannelMask); } - if ((mType == MIXER || mType == DUPLICATING) && mChannelMask != AUDIO_CHANNEL_OUT_STEREO) { - LOG_ALWAYS_FATAL("HAL channel mask %#x not supported for mixed output; " - "must be AUDIO_CHANNEL_OUT_STEREO", mChannelMask); + if ((mType == MIXER || mType == DUPLICATING) + && !isValidPcmSinkChannelMask(mChannelMask)) { + LOG_ALWAYS_FATAL("HAL channel mask %#x not supported for mixed output", + mChannelMask); } mChannelCount = audio_channel_count_from_out_mask(mChannelMask); mHALFormat = mOutput->stream->common.get_format(&mOutput->stream->common); @@ -2044,7 +2068,7 @@ void AudioFlinger::PlaybackThread::threadLoop_removeTracks( if (count > 0) { for (size_t i = 0 ; i < count ; i++) { const sp<Track>& track = tracksToRemove.itemAt(i); - if (!track->isOutputTrack()) { + if (track->isExternalTrack()) { AudioSystem::stopOutput(mId, track->streamType(), track->sessionId()); #ifdef ADD_BATTERY_DATA // to track the speaker usage @@ -2713,6 +2737,26 @@ status_t AudioFlinger::PlaybackThread::releaseAudioPatch_l(const audio_patch_han return status; } +void AudioFlinger::PlaybackThread::addPatchTrack(const sp<PatchTrack>& track) +{ + Mutex::Autolock _l(mLock); + mTracks.add(track); +} + +void AudioFlinger::PlaybackThread::deletePatchTrack(const sp<PatchTrack>& track) +{ + Mutex::Autolock _l(mLock); + destroyTrack_l(track); +} + +void AudioFlinger::PlaybackThread::getAudioPortConfig(struct audio_port_config *config) +{ + ThreadBase::getAudioPortConfig(config); + config->role = AUDIO_PORT_ROLE_SOURCE; + config->ext.mix.hw_module = mOutput->audioHwDev->handle(); + config->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; +} + // ---------------------------------------------------------------------------- AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, @@ -2732,11 +2776,6 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud mNormalFrameCount); mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate); - // FIXME - Current mixer implementation only supports stereo output - if (mChannelCount != FCC_2) { - ALOGE("Invalid audio hardware channel count %d", mChannelCount); - } - // create an NBAIO sink for the HAL output stream, and negotiate mOutputSink = new AudioStreamOutSink(output->stream); size_t numCounterOffers = 0; @@ -3459,6 +3498,10 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask()); + mAudioMixer->setParameter( + name, + AudioMixer::TRACK, + AudioMixer::MIXER_CHANNEL_MASK, (void *)(uintptr_t)mChannelMask); // limit track sample rate to 2 x output sample rate, which changes at re-configuration uint32_t maxSampleRate = mSampleRate * 2; uint32_t reqSampleRate = track->mAudioTrackServerProxy->getSampleRate(); @@ -3697,7 +3740,7 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa reconfig = true; } if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) { - if ((audio_format_t) value != AUDIO_FORMAT_PCM_16_BIT) { + if (!isValidPcmSinkFormat((audio_format_t) value)) { status = BAD_VALUE; } else { // no need to save value, since it's constant @@ -3705,7 +3748,7 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa } } if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) { - if ((audio_channel_mask_t) value != AUDIO_CHANNEL_OUT_STEREO) { + if (!isValidPcmSinkChannelMask((audio_channel_mask_t) value)) { status = BAD_VALUE; } else { // no need to save value, since it's constant @@ -5523,8 +5566,8 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe Mutex::Autolock _l(mLock); track = new RecordTrack(this, client, sampleRate, - format, channelMask, frameCount, sessionId, uid, - *flags); + format, channelMask, frameCount, NULL, sessionId, uid, + *flags, TrackBase::TYPE_DEFAULT); lStatus = track->initCheck(); if (lStatus != NO_ERROR) { @@ -5601,15 +5644,19 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac recordTrack->mState = TrackBase::STARTING_1; mActiveTracks.add(recordTrack); mActiveTracksGen++; - mLock.unlock(); - status_t status = AudioSystem::startInput(mId); - mLock.lock(); - // FIXME should verify that recordTrack is still in mActiveTracks - if (status != NO_ERROR) { - mActiveTracks.remove(recordTrack); - mActiveTracksGen++; - recordTrack->clearSyncStartEvent(); - return status; + status_t status = NO_ERROR; + if (recordTrack->isExternalTrack()) { + mLock.unlock(); + status = AudioSystem::startInput(mId); + mLock.lock(); + // FIXME should verify that recordTrack is still in mActiveTracks + if (status != NO_ERROR) { + mActiveTracks.remove(recordTrack); + mActiveTracksGen++; + recordTrack->clearSyncStartEvent(); + ALOGV("RecordThread::start error %d", status); + return status; + } } // Catch up with current buffer indices if thread is already running. // This is what makes a new client discard all buffered data. If the track's mRsmpInFront @@ -5634,7 +5681,9 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac } startError: - AudioSystem::stopInput(mId); + if (recordTrack->isExternalTrack()) { + AudioSystem::stopInput(mId); + } recordTrack->clearSyncStartEvent(); // FIXME I wonder why we do not reset the state here? return status; @@ -6177,5 +6226,24 @@ status_t AudioFlinger::RecordThread::releaseAudioPatch_l(const audio_patch_handl return status; } +void AudioFlinger::RecordThread::addPatchRecord(const sp<PatchRecord>& record) +{ + Mutex::Autolock _l(mLock); + mTracks.add(record); +} + +void AudioFlinger::RecordThread::deletePatchRecord(const sp<PatchRecord>& record) +{ + Mutex::Autolock _l(mLock); + destroyTrack_l(record); +} + +void AudioFlinger::RecordThread::getAudioPortConfig(struct audio_port_config *config) +{ + ThreadBase::getAudioPortConfig(config); + config->role = AUDIO_PORT_ROLE_SINK; + config->ext.mix.hw_module = mInput->audioHwDev->handle(); + config->ext.mix.usecase.source = mAudioSource; +} }; // namespace android |