summaryrefslogtreecommitdiffstats
path: root/services
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
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')
-rw-r--r--services/audioflinger/AudioFlinger.cpp322
-rw-r--r--services/audioflinger/AudioFlinger.h46
-rw-r--r--services/audioflinger/AudioPolicyService.cpp80
3 files changed, 279 insertions, 169 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);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c47d196..e493a9a 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -43,6 +43,7 @@
#include <system/audio.h>
#include <hardware/audio.h>
+#include <hardware/audio_policy.h>
#include "AudioBufferProvider.h"
@@ -137,12 +138,13 @@ public:
virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const;
- virtual audio_io_handle_t openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- audio_format_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- audio_policy_output_flags_t flags);
+ virtual audio_io_handle_t 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);
virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
audio_io_handle_t output2);
@@ -153,11 +155,11 @@ public:
virtual status_t restoreOutput(audio_io_handle_t output);
- virtual audio_io_handle_t openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- audio_format_t *pFormat,
- uint32_t *pChannels,
- audio_in_acoustics_t acoustics);
+ virtual audio_io_handle_t openInput(audio_module_handle_t module,
+ audio_devices_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ audio_channel_mask_t *pChannelMask);
virtual status_t closeInput(audio_io_handle_t input);
@@ -196,6 +198,8 @@ public:
virtual status_t moveEffects(int sessionId, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput);
+ virtual audio_module_handle_t loadHwModule(const char *name);
+
virtual status_t onTransact(
uint32_t code,
const Parcel& data,
@@ -256,7 +260,7 @@ private:
// RefBase
virtual void onFirstRef();
- audio_hw_device_t* findSuitableHwDev_l(uint32_t devices);
+ audio_hw_device_t* findSuitableHwDev_l(audio_module_handle_t module, uint32_t devices);
void purgeStaleEffects_l();
// standby delay for MIXER and DUPLICATING playback threads is read from property
@@ -1699,15 +1703,30 @@ mutable Mutex mLock; // mutex for process, commands and handl
MVS_FULL,
};
+ class AudioHwDevice {
+ public:
+ AudioHwDevice(const char *moduleName, audio_hw_device_t *hwDevice) :
+ mModuleName(strdup(moduleName)), mHwDevice(hwDevice){}
+ ~AudioHwDevice() { free((void *)mModuleName); }
+
+ const char *moduleName() const { return mModuleName; }
+ audio_hw_device_t *hwDevice() const { return mHwDevice; }
+ private:
+ const char * const mModuleName;
+ audio_hw_device_t * const mHwDevice;
+ };
+
mutable Mutex mLock;
DefaultKeyedVector< pid_t, wp<Client> > mClients; // see ~Client()
mutable Mutex mHardwareLock;
+ // NOTE: If both mLock and mHardwareLock mutexes must be held,
+ // always take mLock before mHardwareLock
// These two fields are immutable after onFirstRef(), so no lock needed to access
audio_hw_device_t* mPrimaryHardwareDev; // mAudioHwDevs[0] or NULL
- Vector<audio_hw_device_t*> mAudioHwDevs;
+ DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs;
// for dump, indicates which hardware operation is currently in progress (but not stream ops)
enum hardware_call_state {
@@ -1757,6 +1776,7 @@ mutable Mutex mLock; // mutex for process, commands and handl
float masterVolume_l() const;
float masterVolumeSW_l() const { return mMasterVolumeSW; }
bool masterMute_l() const { return mMasterMute; }
+ audio_module_handle_t loadHwModule_l(const char *name);
Vector < sp<SyncEvent> > mPendingSyncEvents; // sync events awaiting for a session
// to be created
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 62ab45d..15f4349 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -1329,13 +1329,27 @@ status_t AudioPolicyService::loadPreProcessorConfig(const char *path)
/* implementation of the interface to the policy manager */
extern "C" {
+
+static audio_module_handle_t aps_load_hw_module(void *service,
+ const char *name)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+
+ return af->loadHwModule(name);
+}
+
+// deprecated: replaced by aps_open_output_on_module()
static audio_io_handle_t aps_open_output(void *service,
- uint32_t *pDevices,
- uint32_t *pSamplingRate,
- audio_format_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- audio_policy_output_flags_t flags)
+ 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)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == 0) {
@@ -1343,7 +1357,26 @@ static audio_io_handle_t aps_open_output(void *service,
return 0;
}
- return af->openOutput(pDevices, pSamplingRate, pFormat, pChannels,
+ return af->openOutput((audio_module_handle_t)0, pDevices, pSamplingRate, pFormat, pChannelMask,
+ pLatencyMs, flags);
+}
+
+static audio_io_handle_t aps_open_output_on_module(void *service,
+ 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)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+ ALOGW("%s: %d", __func__, module);
+ return af->openOutput(module, pDevices, pSamplingRate, pFormat, pChannelMask,
pLatencyMs, flags);
}
@@ -1390,12 +1423,29 @@ static int aps_restore_output(void *service, audio_io_handle_t output)
return af->restoreOutput(output);
}
+// deprecated: replaced by aps_open_input_on_module()
static audio_io_handle_t aps_open_input(void *service,
- uint32_t *pDevices,
- uint32_t *pSamplingRate,
- audio_format_t *pFormat,
- uint32_t *pChannels,
- audio_in_acoustics_t acoustics)
+ audio_devices_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ audio_channel_mask_t *pChannelMask,
+ audio_in_acoustics_t acoustics)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+
+ return af->openInput((audio_module_handle_t)0, pDevices, pSamplingRate, pFormat, pChannelMask);
+}
+
+static audio_io_handle_t aps_open_input_on_module(void *service,
+ audio_module_handle_t module,
+ audio_devices_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ audio_channel_mask_t *pChannelMask)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == 0) {
@@ -1403,8 +1453,7 @@ static audio_io_handle_t aps_open_input(void *service,
return 0;
}
- return af->openInput(pDevices, pSamplingRate, pFormat, pChannels,
- acoustics);
+ return af->openInput(module, pDevices, pSamplingRate, pFormat, pChannelMask);
}
static int aps_close_input(void *service, audio_io_handle_t input)
@@ -1503,6 +1552,9 @@ namespace {
stop_tone : aps_stop_tone,
set_voice_volume : aps_set_voice_volume,
move_effects : aps_move_effects,
+ load_hw_module : aps_load_hw_module,
+ open_output_on_module : aps_open_output_on_module,
+ open_input_on_module : aps_open_input_on_module,
};
}; // namespace <unnamed>