summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/AudioFlinger.cpp
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2012-03-29 10:12:40 -0700
committerEric Laurent <elaurent@google.com>2012-04-04 08:44:57 -0700
commita4c5a550e2a3bc237179b8684e51718e05894492 (patch)
treebe7b6d154763ed772738a0126d10e6317920767d /services/audioflinger/AudioFlinger.cpp
parent1a9ed11a472493cac7f6dfcbfac2064526a493ed (diff)
downloadframeworks_av-a4c5a550e2a3bc237179b8684e51718e05894492.zip
frameworks_av-a4c5a550e2a3bc237179b8684e51718e05894492.tar.gz
frameworks_av-a4c5a550e2a3bc237179b8684e51718e05894492.tar.bz2
audio policy: load audio hw modules.
Audio HW modules are now loaded upon request from audio policy manager according to the configuration in audio_policy.conf. Removed hard coded HW module loading by AudioFlinger at init time. Added methods to IAudioFlinger and AudioPolicyInterface to control the loading of audio HW modules. Added methods to open an output or input stream on a specific hw module. Change-Id: I361b294ece1a9b56b2fb39cc64259dbb73b804f4
Diffstat (limited to 'services/audioflinger/AudioFlinger.cpp')
-rw-r--r--services/audioflinger/AudioFlinger.cpp322
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);