diff options
| author | 2011-04-18 16:57:27 -0700 | |
|---|---|---|
| committer | 2011-04-27 16:20:22 -0700 | |
| commit | 31f18889a2c3cd5580db8d2a497a96b7b8a6fd95 (patch) | |
| tree | 066564d02a93ac84aca585d03e77ec7aa2b222ee | |
| parent | 24fc2fb1c541e954b83fd31ea9f786a5e9b45501 (diff) | |
audioflinger: enumerate all the possible audio interfaces
Keep track of the primary interface that handles the master volume,
etc.
Change-Id: Ib0701fccff8d8783a99035a241ab7c8ec75c00ac
Signed-off-by: Dima Zavin <dima@android.com>
| -rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 315 | ||||
| -rw-r--r-- | services/audioflinger/AudioFlinger.h | 44 |
2 files changed, 230 insertions, 129 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 301f46701c0f..e494d05c4b17 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -136,49 +136,98 @@ static void addBatteryData(uint32_t params) { service->addBatteryData(params); } +static int load_audio_interface(const char *if_name, const hw_module_t **mod, + audio_hw_device_t **dev) +{ + int rc; + + rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod); + if (rc) + goto out; + + rc = audio_hw_device_open(*mod, dev); + LOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)", + AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc)); + if (rc) + goto out; + + return 0; + +out: + *mod = NULL; + *dev = NULL; + return rc; +} + +static const char *audio_interfaces[] = { + "primary", + "a2dp", + "usb", +}; +#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0]))) + // ---------------------------------------------------------------------------- AudioFlinger::AudioFlinger() : BnAudioFlinger(), - mAudioHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1) + mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1) { - const hw_module_t *module; - int rc; - char mod_name[PATH_MAX]; + int rc = 0; Mutex::Autolock _l(mLock); + /* TODO: move all this work into an Init() function */ mHardwareStatus = AUDIO_HW_IDLE; - /* get the audio hw module and create an audio_hw device */ - snprintf(mod_name, PATH_MAX, "%s.%s", AUDIO_HARDWARE_MODULE_ID, "primary"); - rc = hw_get_module(mod_name, &module); - if (rc) - return; + for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) { + const hw_module_t *mod; + audio_hw_device_t *dev; - rc = audio_hw_device_open(module, &mAudioHardwareDev); - LOGE_IF(rc, "couldn't open audio hw device (%s)", strerror(-rc)); - if (rc) - return; + rc = load_audio_interface(audio_interfaces[i], &mod, &dev); + if (rc) + continue; + + LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i], + mod->name, mod->id); + mAudioHwDevs.push(dev); + + if (!mPrimaryHardwareDev) { + mPrimaryHardwareDev = dev; + LOGI("Using '%s' (%s.%s) as the primary audio interface", + AUDIO_HARDWARE_INTERFACE, mod->name, mod->id, + audio_interfaces[i]); + } + } mHardwareStatus = AUDIO_HW_INIT; - rc = mAudioHardwareDev->init_check(mAudioHardwareDev); - if (rc == 0) { - AutoMutex lock(mHardwareLock); - mMode = AUDIO_MODE_NORMAL; - mHardwareStatus = AUDIO_HW_SET_MODE; - mAudioHardwareDev->set_mode(mAudioHardwareDev, mMode); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - mAudioHardwareDev->set_master_volume(mAudioHardwareDev, 1.0f); - mHardwareStatus = AUDIO_HW_IDLE; - } else { - LOGE("Couldn't even initialize the stubbed audio hardware!"); + if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) { + LOGE("Primary audio interface not found"); + return; + } + + for (size_t i = 0; i < mAudioHwDevs.size(); i++) { + audio_hw_device_t *dev = mAudioHwDevs[i]; + + mHardwareStatus = AUDIO_HW_INIT; + rc = dev->init_check(dev); + if (rc == 0) { + AutoMutex lock(mHardwareLock); + + mMode = AUDIO_MODE_NORMAL; + mHardwareStatus = AUDIO_HW_SET_MODE; + dev->set_mode(dev, mMode); + mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; + dev->set_master_volume(dev, 1.0f); + mHardwareStatus = AUDIO_HW_IDLE; + } } } AudioFlinger::~AudioFlinger() { + int num_devs = mAudioHwDevs.size(); + while (!mRecordThreads.isEmpty()) { // closeInput() will remove first entry from mRecordThreads closeInput(mRecordThreads.keyAt(0)); @@ -187,12 +236,24 @@ AudioFlinger::~AudioFlinger() // closeOutput() will remove first entry from mPlaybackThreads closeOutput(mPlaybackThreads.keyAt(0)); } - if (mAudioHardwareDev) { - audio_hw_device_close(mAudioHardwareDev); + + for (int i = 0; i < num_devs; i++) { + audio_hw_device_t *dev = mAudioHwDevs[i]; + audio_hw_device_close(dev); } + mAudioHwDevs.clear(); } - +audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices) +{ + /* first matching HW device is returned */ + for (size_t i = 0; i < mAudioHwDevs.size(); i++) { + audio_hw_device_t *dev = mAudioHwDevs[i]; + if ((dev->get_supported_devices(dev) & devices) == devices) + return dev; + } + return NULL; +} status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args) { @@ -291,8 +352,10 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) mRecordThreads.valueAt(i)->dump(fd, args); } - if (mAudioHardwareDev) { - mAudioHardwareDev->dump(mAudioHardwareDev, fd); + // dump all hardware devs + for (size_t i = 0; i < mAudioHwDevs.size(); i++) { + audio_hw_device_t *dev = mAudioHwDevs[i]; + dev->dump(dev, fd); } if (locked) mLock.unlock(); } @@ -468,7 +531,7 @@ status_t AudioFlinger::setMasterVolume(float value) { // scope for the lock AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - if (mAudioHardwareDev->set_master_volume(mAudioHardwareDev, value) == NO_ERROR) { + if (mPrimaryHardwareDev->set_master_volume(mPrimaryHardwareDev, value) == NO_ERROR) { value = 1.0f; } mHardwareStatus = AUDIO_HW_IDLE; @@ -498,7 +561,7 @@ status_t AudioFlinger::setMode(int mode) { // scope for the lock AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_SET_MODE; - ret = mAudioHardwareDev->set_mode(mAudioHardwareDev, mode); + ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode); mHardwareStatus = AUDIO_HW_IDLE; } @@ -521,7 +584,7 @@ status_t AudioFlinger::setMicMute(bool state) AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_SET_MIC_MUTE; - status_t ret = mAudioHardwareDev->set_mic_mute(mAudioHardwareDev, state); + status_t ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state); mHardwareStatus = AUDIO_HW_IDLE; return ret; } @@ -530,7 +593,7 @@ bool AudioFlinger::getMicMute() const { bool state = AUDIO_MODE_INVALID; mHardwareStatus = AUDIO_HW_GET_MIC_MUTE; - mAudioHardwareDev->get_mic_mute(mAudioHardwareDev, &state); + mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state); mHardwareStatus = AUDIO_HW_IDLE; return state; } @@ -658,9 +721,14 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) if (ioHandle == 0) { AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_SET_PARAMETER; - result = mAudioHardwareDev->set_parameters(mAudioHardwareDev, keyValuePairs.string()); + status_t final_result = NO_ERROR; + for (size_t i = 0; i < mAudioHwDevs.size(); i++) { + audio_hw_device_t *dev = mAudioHwDevs[i]; + result = dev->set_parameters(dev, keyValuePairs.string()); + final_result = result ?: final_result; + } mHardwareStatus = AUDIO_HW_IDLE; - return result; + return final_result; } // hold a strong ref on thread in case closeOutput() or closeInput() is called @@ -686,12 +754,14 @@ String8 AudioFlinger::getParameters(int ioHandle, const String8& keys) // ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid()); if (ioHandle == 0) { - char *s; String8 out_s8; - s = mAudioHardwareDev->get_parameters(mAudioHardwareDev, keys.string()); - out_s8 = String8(s); - free(s); + for (size_t i = 0; i < mAudioHwDevs.size(); i++) { + audio_hw_device_t *dev = mAudioHwDevs[i]; + char *s = dev->get_parameters(dev, keys.string()); + out_s8 += String8(s); + free(s); + } return out_s8; } @@ -710,7 +780,7 @@ String8 AudioFlinger::getParameters(int ioHandle, const String8& keys) size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) { - return mAudioHardwareDev->get_input_buffer_size(mAudioHardwareDev, sampleRate, format, channelCount); + return mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount); } unsigned int AudioFlinger::getInputFramesLost(int ioHandle) @@ -737,7 +807,7 @@ status_t AudioFlinger::setVoiceVolume(float value) AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_SET_VOICE_VOLUME; - status_t ret = mAudioHardwareDev->set_voice_volume(mAudioHardwareDev, value); + status_t ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value); mHardwareStatus = AUDIO_HW_IDLE; return ret; @@ -977,7 +1047,7 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args // ---------------------------------------------------------------------------- -AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device) +AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) : ThreadBase(audioFlinger, id), mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), @@ -1190,7 +1260,7 @@ Exit: uint32_t AudioFlinger::PlaybackThread::latency() const { if (mOutput) { - return mOutput->get_latency(mOutput); + return mOutput->stream->get_latency(mOutput->stream); } else { return 0; @@ -1287,7 +1357,7 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) String8 out_s8; char *s; - s = mOutput->common.get_parameters(&mOutput->common, keys.string()); + s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string()); out_s8 = String8(s); free(s); return out_s8; @@ -1322,12 +1392,12 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { void AudioFlinger::PlaybackThread::readOutputParameters() { - mSampleRate = mOutput->common.get_sample_rate(&mOutput->common); - mChannels = mOutput->common.get_channels(&mOutput->common); + mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common); + mChannels = mOutput->stream->common.get_channels(&mOutput->stream->common); mChannelCount = (uint16_t)popcount(mChannels); - mFormat = mOutput->common.get_format(&mOutput->common); - mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->common); - mFrameCount = mOutput->common.get_buffer_size(&mOutput->common) / mFrameSize; + mFormat = mOutput->stream->common.get_format(&mOutput->stream->common); + mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->stream->common); + mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize; // FIXME - Current mixer implementation only supports stereo output: Always // Allocate a stereo buffer even if HW output is mono. @@ -1355,9 +1425,9 @@ status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, ui if (mOutput == 0) { return INVALID_OPERATION; } - *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->common); + *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common); - return mOutput->get_render_position(mOutput, dspFrames); + return mOutput->stream->get_render_position(mOutput->stream, dspFrames); } uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId) @@ -1428,7 +1498,7 @@ void AudioFlinger::PlaybackThread::setMode(uint32_t mode) // ---------------------------------------------------------------------------- -AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device) +AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) : PlaybackThread(audioFlinger, output, id, device), mAudioMixer(0) { @@ -1487,7 +1557,7 @@ bool AudioFlinger::MixerThread::threadLoop() mSuspended) { if (!mStandby) { LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended); - mOutput->common.standby(&mOutput->common); + mOutput->stream->common.standby(&mOutput->stream->common); mStandby = true; mBytesWritten = 0; } @@ -1564,7 +1634,7 @@ bool AudioFlinger::MixerThread::threadLoop() mInWrite = true; mBytesWritten += mixBufferSize; - int bytesWritten = (int)mOutput->write(mOutput, mMixBuffer, mixBufferSize); + int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize); if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; mInWrite = false; @@ -1599,7 +1669,7 @@ bool AudioFlinger::MixerThread::threadLoop() } if (!mStandby) { - mOutput->common.standby(&mOutput->common); + mOutput->stream->common.standby(&mOutput->stream->common); } LOGV("MixerThread %p exiting", this); @@ -1903,13 +1973,13 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() } if (status == NO_ERROR) { - status = mOutput->common.set_parameters(&mOutput->common, + status = mOutput->stream->common.set_parameters(&mOutput->stream->common, keyValuePair.string()); if (!mStandby && status == INVALID_OPERATION) { - mOutput->common.standby(&mOutput->common); + mOutput->stream->common.standby(&mOutput->stream->common); mStandby = true; mBytesWritten = 0; - status = mOutput->common.set_parameters(&mOutput->common, + status = mOutput->stream->common.set_parameters(&mOutput->stream->common, keyValuePair.string()); } if (status == NO_ERROR && reconfig) { @@ -1954,7 +2024,7 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16> uint32_t AudioFlinger::MixerThread::activeSleepTimeUs() { - return (uint32_t)(mOutput->get_latency(mOutput) * 1000) / 2; + return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2; } uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() @@ -1968,7 +2038,7 @@ uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() } // ---------------------------------------------------------------------------- -AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device) +AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) : PlaybackThread(audioFlinger, output, id, device) { mType = PlaybackThread::DIRECT; @@ -2118,7 +2188,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // wait until we have something to do... if (!mStandby) { LOGV("Audio hardware entering standby, mixer %p\n", this); - mOutput->common.standby(&mOutput->common); + mOutput->stream->common.standby(&mOutput->stream->common); mStandby = true; mBytesWritten = 0; } @@ -2203,7 +2273,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // If audio HAL implements volume control, // force software volume to nominal value - if (mOutput->set_volume(mOutput, left, right) == NO_ERROR) { + if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) { left = 1.0f; right = 1.0f; } @@ -2326,7 +2396,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() mLastWriteTime = systemTime(); mInWrite = true; mBytesWritten += mixBufferSize; - int bytesWritten = (int)mOutput->write(mOutput, mMixBuffer, mixBufferSize); + int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize); if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; mInWrite = false; @@ -2348,7 +2418,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } if (!mStandby) { - mOutput->common.standby(&mOutput->common); + mOutput->stream->common.standby(&mOutput->stream->common); } LOGV("DirectOutputThread %p exiting", this); @@ -2388,13 +2458,13 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() } } if (status == NO_ERROR) { - status = mOutput->common.set_parameters(&mOutput->common, + status = mOutput->stream->common.set_parameters(&mOutput->stream->common, keyValuePair.string()); if (!mStandby && status == INVALID_OPERATION) { - mOutput->common.standby(&mOutput->common); + mOutput->stream->common.standby(&mOutput->stream->common); mStandby = true; mBytesWritten = 0; - status = mOutput->common.set_parameters(&mOutput->common, + status = mOutput->stream->common.set_parameters(&mOutput->stream->common, keyValuePair.string()); } if (status == NO_ERROR && reconfig) { @@ -2416,7 +2486,7 @@ uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() { uint32_t time; if (audio_is_linear_pcm(mFormat)) { - time = (uint32_t)(mOutput->get_latency(mOutput) * 1000) / 2; + time = (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2; } else { time = 10000; } @@ -3705,7 +3775,7 @@ status_t AudioFlinger::RecordHandle::onTransact( // ---------------------------------------------------------------------------- -AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_in *input, uint32_t sampleRate, uint32_t channels, int id) : +AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) : ThreadBase(audioFlinger, id), mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) { @@ -3751,7 +3821,7 @@ bool AudioFlinger::RecordThread::threadLoop() checkForNewParameters_l(); if (mActiveTrack == 0 && mConfigEvents.isEmpty()) { if (!mStandby) { - mInput->common.standby(&mInput->common); + mInput->stream->common.standby(&mInput->stream->common); mStandby = true; } @@ -3766,7 +3836,7 @@ bool AudioFlinger::RecordThread::threadLoop() if (mActiveTrack != 0) { if (mActiveTrack->mState == TrackBase::PAUSING) { if (!mStandby) { - mInput->common.standby(&mInput->common); + mInput->stream->common.standby(&mInput->stream->common); mStandby = true; } mActiveTrack.clear(); @@ -3832,10 +3902,10 @@ bool AudioFlinger::RecordThread::threadLoop() if (framesOut && mFrameCount == mRsmpInIndex) { if (framesOut == mFrameCount && ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) { - mBytesRead = mInput->read(mInput, buffer.raw, mInputBytes); + mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes); framesOut = 0; } else { - mBytesRead = mInput->read(mInput, mRsmpInBuffer, mInputBytes); + mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes); mRsmpInIndex = 0; } if (mBytesRead < 0) { @@ -3843,7 +3913,7 @@ bool AudioFlinger::RecordThread::threadLoop() if (mActiveTrack->mState == TrackBase::ACTIVE) { // Force input into standby so that it tries to // recover at next read attempt - mInput->common.standby(&mInput->common); + mInput->stream->common.standby(&mInput->stream->common); usleep(5000); } mRsmpInIndex = mFrameCount; @@ -3898,7 +3968,7 @@ bool AudioFlinger::RecordThread::threadLoop() } if (!mStandby) { - mInput->common.standby(&mInput->common); + mInput->stream->common.standby(&mInput->stream->common); } mActiveTrack.clear(); @@ -4030,13 +4100,13 @@ status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* int channelCount; if (framesReady == 0) { - mBytesRead = mInput->read(mInput, mRsmpInBuffer, mInputBytes); + mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes); if (mBytesRead < 0) { LOGE("RecordThread::getNextBuffer() Error reading audio input"); if (mActiveTrack->mState == TrackBase::ACTIVE) { // Force input into standby so that it tries to // recover at next read attempt - mInput->common.standby(&mInput->common); + mInput->stream->common.standby(&mInput->stream->common); usleep(5000); } buffer->raw = 0; @@ -4103,17 +4173,17 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() } } if (status == NO_ERROR) { - status = mInput->common.set_parameters(&mInput->common, keyValuePair.string()); + status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string()); if (status == INVALID_OPERATION) { - mInput->common.standby(&mInput->common); - status = mInput->common.set_parameters(&mInput->common, keyValuePair.string()); + mInput->stream->common.standby(&mInput->stream->common); + status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string()); } if (reconfig) { if (status == BAD_VALUE && - reqFormat == mInput->common.get_format(&mInput->common) && + reqFormat == mInput->stream->common.get_format(&mInput->stream->common) && reqFormat == AUDIO_FORMAT_PCM_16_BIT && - ((int)mInput->common.get_sample_rate(&mInput->common) <= (2 * reqSamplingRate)) && - (popcount(mInput->common.get_channels(&mInput->common)) < 3) && + ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) && + (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) && (reqChannelCount < 3)) { status = NO_ERROR; } @@ -4138,7 +4208,7 @@ String8 AudioFlinger::RecordThread::getParameters(const String8& keys) char *s; String8 out_s8; - s = mInput->common.get_parameters(&mInput->common, keys.string()); + s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string()); out_s8 = String8(s); free(s); return out_s8; @@ -4173,12 +4243,12 @@ void AudioFlinger::RecordThread::readInputParameters() if (mResampler) delete mResampler; mResampler = 0; - mSampleRate = mInput->common.get_sample_rate(&mInput->common); - mChannels = mInput->common.get_channels(&mInput->common); + mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common); + mChannels = mInput->stream->common.get_channels(&mInput->stream->common); mChannelCount = (uint16_t)popcount(mChannels); - mFormat = mInput->common.get_format(&mInput->common); - mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->common); - mInputBytes = mInput->common.get_buffer_size(&mInput->common); + mFormat = mInput->stream->common.get_format(&mInput->stream->common); + mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->stream->common); + mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common); mFrameCount = mInputBytes / mFrameSize; mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount]; @@ -4208,7 +4278,7 @@ void AudioFlinger::RecordThread::readInputParameters() unsigned int AudioFlinger::RecordThread::getInputFramesLost() { - return mInput->get_input_frames_lost(mInput); + return mInput->stream->get_input_frames_lost(mInput->stream); } // ---------------------------------------------------------------------------- @@ -4227,7 +4297,8 @@ int AudioFlinger::openOutput(uint32_t *pDevices, uint32_t format = pFormat ? *pFormat : 0; uint32_t channels = pChannels ? *pChannels : 0; uint32_t latency = pLatencyMs ? *pLatencyMs : 0; - struct audio_stream_out *output; + audio_stream_out_t *outStream; + audio_hw_device_t *outHwDev; LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x", pDevices ? *pDevices : 0, @@ -4239,23 +4310,27 @@ int AudioFlinger::openOutput(uint32_t *pDevices, if (pDevices == NULL || *pDevices == 0) { return 0; } + Mutex::Autolock _l(mLock); - status = mAudioHardwareDev->open_output_stream(mAudioHardwareDev, *pDevices, - (int *)&format, - &channels, - &samplingRate, - &output); + outHwDev = findSuitableHwDev_l(*pDevices); + if (outHwDev == NULL) + return 0; + + status = outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format, + &channels, &samplingRate, &outStream); LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d", - output, + outStream, samplingRate, format, channels, status); mHardwareStatus = AUDIO_HW_IDLE; - if (output != 0) { + if (outStream != NULL) { + AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream); int id = nextUniqueId_l(); + if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) || (format != AUDIO_FORMAT_PCM_16_BIT) || (channels != AUDIO_CHANNEL_OUT_STEREO)) { @@ -4329,7 +4404,9 @@ status_t AudioFlinger::closeOutput(int output) thread->exit(); if (thread->type() != PlaybackThread::DUPLICATING) { - mAudioHardwareDev->close_output_stream(mAudioHardwareDev, thread->getOutput()); + AudioStreamOut *out = thread->getOutput(); + out->hwDev->close_output_stream(out->hwDev, out->stream); + delete out; } return NO_ERROR; } @@ -4379,22 +4456,25 @@ int AudioFlinger::openInput(uint32_t *pDevices, uint32_t reqSamplingRate = samplingRate; uint32_t reqFormat = format; uint32_t reqChannels = channels; - struct audio_stream_in *input; + audio_stream_in_t *inStream; + audio_hw_device_t *inHwDev; if (pDevices == NULL || *pDevices == 0) { return 0; } + Mutex::Autolock _l(mLock); - status = mAudioHardwareDev->open_input_stream(mAudioHardwareDev, - *pDevices, - (int *)&format, - &channels, - &samplingRate, + inHwDev = findSuitableHwDev_l(*pDevices); + if (inHwDev == NULL) + return 0; + + status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format, + &channels, &samplingRate, (audio_in_acoustics_t)acoustics, - &input); + &inStream); LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d", - input, + inStream, samplingRate, format, channels, @@ -4404,21 +4484,20 @@ int AudioFlinger::openInput(uint32_t *pDevices, // If the input could not be opened with the requested parameters and we can handle the conversion internally, // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo // or stereo to mono conversions on 16 bit PCM inputs. - if (input == 0 && status == BAD_VALUE && + if (inStream == NULL && status == BAD_VALUE && reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT && (samplingRate <= 2 * reqSamplingRate) && (popcount(channels) < 3) && (popcount(reqChannels) < 3)) { LOGV("openInput() reopening with proposed sampling rate and channels"); - status = mAudioHardwareDev->open_input_stream(mAudioHardwareDev, - *pDevices, - (int *)&format, - &channels, - &samplingRate, + status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format, + &channels, &samplingRate, (audio_in_acoustics_t)acoustics, - &input); + &inStream); } - if (input != 0) { + if (inStream != NULL) { + AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream); + int id = nextUniqueId_l(); // Start record thread thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id); @@ -4428,7 +4507,7 @@ int AudioFlinger::openInput(uint32_t *pDevices, if (pFormat) *pFormat = format; if (pChannels) *pChannels = reqChannels; - input->common.standby(&input->common); + input->stream->common.standby(&input->stream->common); // notify client processes of the new input creation thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED); @@ -4457,7 +4536,9 @@ status_t AudioFlinger::closeInput(int input) } thread->exit(); - mAudioHardwareDev->close_input_stream(mAudioHardwareDev, thread->getInput()); + AudioStreamIn *in = thread->getInput(); + in->hwDev->close_input_stream(in->hwDev, in->stream); + delete in; return NO_ERROR; } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 4ac1ee39ec8a..94f786112cbb 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -32,12 +32,14 @@ #include <utils/Errors.h> #include <utils/threads.h> #include <utils/SortedVector.h> +#include <utils/TypeHelpers.h> #include <utils/Vector.h> #include <binder/BinderService.h> #include <binder/MemoryDealer.h> #include <hardware/audio.h> +#include <hardware/audio_hal.h> #include "AudioBufferProvider.h" @@ -49,7 +51,6 @@ class AudioMixer; class AudioBuffer; class AudioResampler; - // ---------------------------------------------------------------------------- #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) @@ -211,6 +212,7 @@ private: AudioFlinger(); virtual ~AudioFlinger(); + audio_hw_device_t* findSuitableHwDev_l(uint32_t devices); // Internal dump utilites. status_t dumpPermissionDenial(int fd, const Vector<String16>& args); @@ -268,6 +270,8 @@ private: class EffectModule; class EffectHandle; class EffectChain; + struct AudioStreamOut; + struct AudioStreamIn; class ThreadBase : public Thread { public: @@ -554,7 +558,7 @@ private: DuplicatingThread* mSourceThread; }; // end of OutputTrack - PlaybackThread (const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device); + PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device); virtual ~PlaybackThread(); virtual status_t dump(int fd, const Vector<String16>& args); @@ -588,7 +592,7 @@ private: int sessionId, status_t *status); - struct audio_stream_out* getOutput() { return mOutput; } + AudioStreamOut* getOutput() { return mOutput; } virtual int type() const { return mType; } void suspend() { mSuspended++; } @@ -690,7 +694,7 @@ private: SortedVector< sp<Track> > mTracks; // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1]; - struct audio_stream_out* mOutput; + AudioStreamOut* mOutput; float mMasterVolume; nsecs_t mLastWriteTime; int mNumWrites; @@ -703,7 +707,7 @@ private: class MixerThread : public PlaybackThread { public: MixerThread (const sp<AudioFlinger>& audioFlinger, - struct audio_stream_out* output, + AudioStreamOut* output, int id, uint32_t device); virtual ~MixerThread(); @@ -730,7 +734,7 @@ private: class DirectOutputThread : public PlaybackThread { public: - DirectOutputThread (const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device); + DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device); ~DirectOutputThread(); // Thread virtuals @@ -854,7 +858,7 @@ private: RecordThread(const sp<AudioFlinger>& audioFlinger, - struct audio_stream_in *input, + AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id); @@ -867,7 +871,7 @@ private: status_t start(RecordTrack* recordTrack); void stop(RecordTrack* recordTrack); status_t dump(int fd, const Vector<String16>& args); - struct audio_stream_in* getInput() { return mInput; } + AudioStreamIn* getInput() { return mInput; } virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); @@ -879,7 +883,7 @@ private: private: RecordThread(); - struct audio_stream_in *mInput; + AudioStreamIn *mInput; sp<RecordTrack> mActiveTrack; Condition mStartStopCond; AudioResampler *mResampler; @@ -1159,17 +1163,32 @@ private: uint32_t mStrategy; // strategy for this effect chain }; + struct AudioStreamOut { + audio_hw_device_t *hwDev; + audio_stream_out_t *stream; + + AudioStreamOut(audio_hw_device_t *dev, audio_stream_out_t *out) : + hwDev(dev), stream(out) {} + }; + + struct AudioStreamIn { + audio_hw_device_t *hwDev; + audio_stream_in_t *stream; + + AudioStreamIn(audio_hw_device_t *dev, audio_stream_in_t *in) : + hwDev(dev), stream(in) {} + }; + friend class RecordThread; friend class PlaybackThread; - mutable Mutex mLock; DefaultKeyedVector< pid_t, wp<Client> > mClients; mutable Mutex mHardwareLock; - struct audio_hw_device* mAudioHardwareDev; - Vector<struct audio_hw_device *> mAudioHwDevs; + audio_hw_device_t* mPrimaryHardwareDev; + Vector<audio_hw_device_t*> mAudioHwDevs; mutable int mHardwareStatus; @@ -1186,6 +1205,7 @@ private: }; + // ---------------------------------------------------------------------------- }; // namespace android |