diff options
Diffstat (limited to 'services/audioflinger/AudioFlinger.cpp')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 322 |
1 files changed, 180 insertions, 142 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index e926292..9e6a6df 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -149,13 +149,6 @@ out: return rc; } -static const char * const audio_interfaces[] = { - AUDIO_HARDWARE_MODULE_ID_PRIMARY, - AUDIO_HARDWARE_MODULE_ID_A2DP, - AUDIO_HARDWARE_MODULE_ID_USB, -}; -#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0]))) - // ---------------------------------------------------------------------------- AudioFlinger::AudioFlinger() @@ -191,87 +184,9 @@ void AudioFlinger::onFirstRef() } } - for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) { - const hw_module_t *mod; - audio_hw_device_t *dev; - - rc = load_audio_interface(audio_interfaces[i], &mod, &dev); - if (rc) - continue; - - ALOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i], - mod->name, mod->id); - mAudioHwDevs.push(dev); - - if (mPrimaryHardwareDev == NULL) { - mPrimaryHardwareDev = dev; - ALOGI("Using '%s' (%s.%s) as the primary audio interface", - mod->name, mod->id, audio_interfaces[i]); - } - } - - if (mPrimaryHardwareDev == NULL) { - ALOGE("Primary audio interface not found"); - // proceed, all later accesses to mPrimaryHardwareDev verify it's safe with initCheck() - } - - // Currently (mPrimaryHardwareDev == NULL) == (mAudioHwDevs.size() == 0), but the way the - // primary HW dev is selected can change so these conditions might not always be equivalent. - // When that happens, re-visit all the code that assumes this. - - AutoMutex lock(mHardwareLock); - - // Determine the level of master volume support the primary audio HAL has, - // and set the initial master volume at the same time. - float initialVolume = 1.0; - mMasterVolumeSupportLvl = MVS_NONE; - if (0 == mPrimaryHardwareDev->init_check(mPrimaryHardwareDev)) { - audio_hw_device_t *dev = mPrimaryHardwareDev; - - mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME; - if ((NULL != dev->get_master_volume) && - (NO_ERROR == dev->get_master_volume(dev, &initialVolume))) { - mMasterVolumeSupportLvl = MVS_FULL; - } else { - mMasterVolumeSupportLvl = MVS_SETONLY; - initialVolume = 1.0; - } - - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - if ((NULL == dev->set_master_volume) || - (NO_ERROR != dev->set_master_volume(dev, initialVolume))) { - mMasterVolumeSupportLvl = MVS_NONE; - } - mHardwareStatus = AUDIO_HW_IDLE; - } - - // Set the mode for each audio HAL, and try to set the initial volume (if - // supported) for all of the non-primary audio HALs. - 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); - mHardwareStatus = AUDIO_HW_IDLE; - if (rc == 0) { - mMode = AUDIO_MODE_NORMAL; // assigned multiple times with same value - mHardwareStatus = AUDIO_HW_SET_MODE; - dev->set_mode(dev, mMode); - - if ((dev != mPrimaryHardwareDev) && - (NULL != dev->set_master_volume)) { - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - dev->set_master_volume(dev, initialVolume); - } - - mHardwareStatus = AUDIO_HW_IDLE; - } - } - - mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl) - ? initialVolume - : 1.0; - mMasterVolume = initialVolume; + mMode = AUDIO_MODE_NORMAL; + mMasterVolumeSW = 1.0; + mMasterVolume = 1.0; mHardwareStatus = AUDIO_HW_IDLE; } @@ -289,18 +204,41 @@ AudioFlinger::~AudioFlinger() for (size_t i = 0; i < mAudioHwDevs.size(); i++) { // no mHardwareLock needed, as there are no other references to this - audio_hw_device_close(mAudioHwDevs[i]); + audio_hw_device_close(mAudioHwDevs.valueAt(i)->hwDevice()); + delete mAudioHwDevs.valueAt(i); } } -audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices) +static const char * const audio_interfaces[] = { + AUDIO_HARDWARE_MODULE_ID_PRIMARY, + AUDIO_HARDWARE_MODULE_ID_A2DP, + AUDIO_HARDWARE_MODULE_ID_USB, +}; +#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0]))) + +audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(audio_module_handle_t module, uint32_t devices) { - /* first matching HW device is returned */ + // if module is 0, the request comes from an old policy manager and we should load + // well known modules + if (module == 0) { + ALOGW("findSuitableHwDev_l() loading well know audio hw modules"); + for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) { + loadHwModule_l(audio_interfaces[i]); + } + } else { + // check a match for the requested module handle + AudioHwDevice *audioHwdevice = mAudioHwDevs.valueFor(module); + if (audioHwdevice != NULL) { + return audioHwdevice->hwDevice(); + } + } + // then try to find a module supporting the requested device. for (size_t i = 0; i < mAudioHwDevs.size(); i++) { - audio_hw_device_t *dev = mAudioHwDevs[i]; + audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice(); if ((dev->get_supported_devices(dev) & devices) == devices) return dev; } + return NULL; } @@ -411,7 +349,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) // dump all hardware devs for (size_t i = 0; i < mAudioHwDevs.size(); i++) { - audio_hw_device_t *dev = mAudioHwDevs[i]; + audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice(); dev->dump(dev, fd); } if (locked) mLock.unlock(); @@ -610,11 +548,13 @@ status_t AudioFlinger::setMasterVolume(float value) float swmv = value; + Mutex::Autolock _l(mLock); + // when hw supports master volume, don't scale in sw mixer if (MVS_NONE != mMasterVolumeSupportLvl) { for (size_t i = 0; i < mAudioHwDevs.size(); i++) { AutoMutex lock(mHardwareLock); - audio_hw_device_t *dev = mAudioHwDevs[i]; + audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice(); mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; if (NULL != dev->set_master_volume) { @@ -626,7 +566,6 @@ status_t AudioFlinger::setMasterVolume(float value) swmv = 1.0; } - Mutex::Autolock _l(mLock); mMasterVolume = value; mMasterVolumeSW = swmv; for (size_t i = 0; i < mPlaybackThreads.size(); i++) @@ -853,22 +792,22 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& // ioHandle == 0 means the parameters are global to the audio hardware interface if (ioHandle == 0) { + Mutex::Autolock _l(mLock); status_t final_result = NO_ERROR; { - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_PARAMETER; - for (size_t i = 0; i < mAudioHwDevs.size(); i++) { - audio_hw_device_t *dev = mAudioHwDevs[i]; - status_t result = dev->set_parameters(dev, keyValuePairs.string()); - final_result = result ?: final_result; - } - mHardwareStatus = AUDIO_HW_IDLE; + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_HW_SET_PARAMETER; + for (size_t i = 0; i < mAudioHwDevs.size(); i++) { + audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice(); + status_t result = dev->set_parameters(dev, keyValuePairs.string()); + final_result = result ?: final_result; + } + mHardwareStatus = AUDIO_HW_IDLE; } // disable AEC and NS if the device is a BT SCO headset supporting those pre processings AudioParameter param = AudioParameter(keyValuePairs); String8 value; if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) { - Mutex::Autolock _l(mLock); bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF); if (mBtNrecIsOff != btNrecIsOff) { for (size_t i = 0; i < mRecordThreads.size(); i++) { @@ -923,6 +862,8 @@ String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& k // ALOGV("getParameters() io %d, keys %s, tid %d, calling pid %d", // ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid()); + Mutex::Autolock _l(mLock); + if (ioHandle == 0) { String8 out_s8; @@ -931,7 +872,7 @@ String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& k { AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_GET_PARAMETER; - audio_hw_device_t *dev = mAudioHwDevs[i]; + audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice(); s = dev->get_parameters(dev, keys.string()); mHardwareStatus = AUDIO_HW_IDLE; } @@ -941,8 +882,6 @@ String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& k return out_s8; } - Mutex::Autolock _l(mLock); - PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle); if (playbackThread != NULL) { return playbackThread->getParameters(keys); @@ -5663,28 +5602,84 @@ audio_stream_t* AudioFlinger::RecordThread::stream() const // ---------------------------------------------------------------------------- -audio_io_handle_t AudioFlinger::openOutput(uint32_t *pDevices, - uint32_t *pSamplingRate, - audio_format_t *pFormat, - uint32_t *pChannels, - uint32_t *pLatencyMs, - audio_policy_output_flags_t flags) +audio_module_handle_t AudioFlinger::loadHwModule(const char *name) +{ + if (!settingsAllowed()) { + return 0; + } + Mutex::Autolock _l(mLock); + return loadHwModule_l(name); +} + +// loadHwModule_l() must be called with AudioFlinger::mLock held +audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name) +{ + for (size_t i = 0; i < mAudioHwDevs.size(); i++) { + if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) { + ALOGW("loadHwModule() module %s already loaded", name); + return mAudioHwDevs.keyAt(i); + } + } + + const hw_module_t *mod; + audio_hw_device_t *dev; + + int rc = load_audio_interface(name, &mod, &dev); + if (rc) { + ALOGI("loadHwModule() error %d loading module %s ", rc, name); + return 0; + } + + mHardwareStatus = AUDIO_HW_INIT; + rc = dev->init_check(dev); + mHardwareStatus = AUDIO_HW_IDLE; + if (rc) { + ALOGI("loadHwModule() init check error %d for module %s ", rc, name); + return 0; + } + + if ((mMasterVolumeSupportLvl != MVS_NONE) && + (NULL != dev->set_master_volume)) { + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; + dev->set_master_volume(dev, mMasterVolume); + mHardwareStatus = AUDIO_HW_IDLE; + } + + audio_module_handle_t handle = nextUniqueId(); + mAudioHwDevs.add(handle, new AudioHwDevice(name, dev)); + + ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d", + name, mod->name, mod->id, handle); + + return handle; + +} + +audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + uint32_t *pLatencyMs, + audio_policy_output_flags_t flags) { status_t status; PlaybackThread *thread = NULL; uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0; audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT; - uint32_t channels = pChannels ? *pChannels : 0; + audio_channel_mask_t channelMask = pChannelMask ? *pChannelMask : 0; uint32_t latency = pLatencyMs ? *pLatencyMs : 0; audio_stream_out_t *outStream; audio_hw_device_t *outHwDev; - ALOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x", - pDevices ? *pDevices : 0, - samplingRate, - format, - channels, - flags); + ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %d, Channels %x, flags %x", + module, + pDevices ? *pDevices : 0, + samplingRate, + format, + channelMask, + flags); if (pDevices == NULL || *pDevices == 0) { return 0; @@ -5692,19 +5687,19 @@ audio_io_handle_t AudioFlinger::openOutput(uint32_t *pDevices, Mutex::Autolock _l(mLock); - outHwDev = findSuitableHwDev_l(*pDevices); + outHwDev = findSuitableHwDev_l(module, *pDevices); if (outHwDev == NULL) return 0; mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; status = outHwDev->open_output_stream(outHwDev, *pDevices, &format, - &channels, &samplingRate, &outStream); + &channelMask, &samplingRate, &outStream); mHardwareStatus = AUDIO_HW_IDLE; ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d", outStream, samplingRate, format, - channels, + channelMask, status); if (outStream != NULL) { @@ -5713,7 +5708,7 @@ audio_io_handle_t AudioFlinger::openOutput(uint32_t *pDevices, if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) || (format != AUDIO_FORMAT_PCM_16_BIT) || - (channels != AUDIO_CHANNEL_OUT_STEREO)) { + (channelMask != AUDIO_CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output, id, *pDevices); ALOGV("openOutput() created direct output: ID %d thread %p", id, thread); } else { @@ -5724,11 +5719,55 @@ audio_io_handle_t AudioFlinger::openOutput(uint32_t *pDevices, if (pSamplingRate != NULL) *pSamplingRate = samplingRate; if (pFormat != NULL) *pFormat = format; - if (pChannels != NULL) *pChannels = channels; + if (pChannelMask != NULL) *pChannelMask = channelMask; if (pLatencyMs != NULL) *pLatencyMs = thread->latency(); // notify client processes of the new output creation thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); + + // the first primary output opened designates the primary hw device + if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_POLICY_OUTPUT_FLAG_PRIMARY)) { + ALOGI("Using module %d has the primary audio interface", module); + mPrimaryHardwareDev = outHwDev; + + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_HW_SET_MODE; + outHwDev->set_mode(outHwDev, mMode); + + // Determine the level of master volume support the primary audio HAL has, + // and set the initial master volume at the same time. + float initialVolume = 1.0; + mMasterVolumeSupportLvl = MVS_NONE; + + mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME; + if ((NULL != outHwDev->get_master_volume) && + (NO_ERROR == outHwDev->get_master_volume(outHwDev, &initialVolume))) { + mMasterVolumeSupportLvl = MVS_FULL; + } else { + mMasterVolumeSupportLvl = MVS_SETONLY; + initialVolume = 1.0; + } + + mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; + if ((NULL == outHwDev->set_master_volume) || + (NO_ERROR != outHwDev->set_master_volume(outHwDev, initialVolume))) { + mMasterVolumeSupportLvl = MVS_NONE; + } + // now that we have a primary device, initialize master volume on other devices + for (size_t i = 0; i < mAudioHwDevs.size(); i++) { + audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice(); + + if ((dev != mPrimaryHardwareDev) && + (NULL != dev->set_master_volume)) { + dev->set_master_volume(dev, initialVolume); + } + } + mHardwareStatus = AUDIO_HW_IDLE; + mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl) + ? initialVolume + : 1.0; + mMasterVolume = initialVolume; + } return id; } @@ -5826,20 +5865,20 @@ status_t AudioFlinger::restoreOutput(audio_io_handle_t output) return NO_ERROR; } -audio_io_handle_t AudioFlinger::openInput(uint32_t *pDevices, - uint32_t *pSamplingRate, - audio_format_t *pFormat, - uint32_t *pChannels, - audio_in_acoustics_t acoustics) +audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + uint32_t *pChannelMask) { status_t status; RecordThread *thread = NULL; uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0; audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT; - uint32_t channels = pChannels ? *pChannels : 0; + audio_channel_mask_t channelMask = pChannelMask ? *pChannelMask : 0; uint32_t reqSamplingRate = samplingRate; audio_format_t reqFormat = format; - uint32_t reqChannels = channels; + audio_channel_mask_t reqChannels = channelMask; audio_stream_in_t *inStream; audio_hw_device_t *inHwDev; @@ -5849,20 +5888,19 @@ audio_io_handle_t AudioFlinger::openInput(uint32_t *pDevices, Mutex::Autolock _l(mLock); - inHwDev = findSuitableHwDev_l(*pDevices); + inHwDev = findSuitableHwDev_l(module, *pDevices); if (inHwDev == NULL) return 0; status = inHwDev->open_input_stream(inHwDev, *pDevices, &format, - &channels, &samplingRate, - acoustics, + &channelMask, &samplingRate, + (audio_in_acoustics_t)0, &inStream); - ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d", + ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, status %d", inStream, samplingRate, format, - channels, - acoustics, + channelMask, status); // If the input could not be opened with the requested parameters and we can handle the conversion internally, @@ -5871,11 +5909,11 @@ audio_io_handle_t AudioFlinger::openInput(uint32_t *pDevices, if (inStream == NULL && status == BAD_VALUE && reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT && (samplingRate <= 2 * reqSamplingRate) && - (popcount(channels) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) { + (popcount(channelMask) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) { ALOGV("openInput() reopening with proposed sampling rate and channels"); status = inHwDev->open_input_stream(inHwDev, *pDevices, &format, - &channels, &samplingRate, - acoustics, + &channelMask, &samplingRate, + (audio_in_acoustics_t)0, &inStream); } @@ -5897,7 +5935,7 @@ audio_io_handle_t AudioFlinger::openInput(uint32_t *pDevices, ALOGV("openInput() created record thread: ID %d thread %p", id, thread); if (pSamplingRate != NULL) *pSamplingRate = reqSamplingRate; if (pFormat != NULL) *pFormat = format; - if (pChannels != NULL) *pChannels = reqChannels; + if (pChannelMask != NULL) *pChannelMask = reqChannels; input->stream->common.standby(&input->stream->common); |