summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/IAudioFlinger.h26
-rw-r--r--media/libmedia/IAudioFlinger.cpp105
-rw-r--r--services/audioflinger/AudioFlinger.cpp322
-rw-r--r--services/audioflinger/AudioFlinger.h46
-rw-r--r--services/audioflinger/AudioPolicyService.cpp80
5 files changed, 356 insertions, 223 deletions
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 8239b0e..9e938d1 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -29,6 +29,7 @@
#include <media/IAudioFlingerClient.h>
#include <system/audio.h>
#include <system/audio_policy.h>
+#include <hardware/audio_policy.h>
#include <hardware/audio_effect.h>
#include <media/IEffect.h>
#include <media/IEffectClient.h>
@@ -126,23 +127,24 @@ public:
// retrieve the audio recording buffer size
virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const = 0;
- 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) = 0;
+ 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) = 0;
virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
audio_io_handle_t output2) = 0;
virtual status_t closeOutput(audio_io_handle_t output) = 0;
virtual status_t suspendOutput(audio_io_handle_t output) = 0;
virtual status_t restoreOutput(audio_io_handle_t output) = 0;
- virtual audio_io_handle_t openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- audio_format_t *pFormat,
- uint32_t *pChannels,
- audio_in_acoustics_t acoustics) = 0;
+ 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) = 0;
virtual status_t closeInput(audio_io_handle_t input) = 0;
virtual status_t setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output) = 0;
@@ -178,6 +180,8 @@ public:
virtual status_t moveEffects(int session, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput) = 0;
+
+ virtual audio_module_handle_t loadHwModule(const char *name) = 0;
};
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index ce10c8e..81e259a 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -69,7 +69,8 @@ enum {
QUERY_EFFECT,
GET_EFFECT_DESCRIPTOR,
CREATE_EFFECT,
- MOVE_EFFECTS
+ MOVE_EFFECTS,
+ LOAD_HW_MODULE
};
class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -355,38 +356,40 @@ public:
return reply.readInt32();
}
- 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)
{
Parcel data, reply;
- uint32_t devices = pDevices ? *pDevices : 0;
+ audio_devices_t devices = pDevices ? *pDevices : (audio_devices_t)0;
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 : (audio_channel_mask_t)0;
uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(module);
data.writeInt32(devices);
data.writeInt32(samplingRate);
data.writeInt32(format);
- data.writeInt32(channels);
+ data.writeInt32(channelMask);
data.writeInt32(latency);
data.writeInt32((int32_t) flags);
remote()->transact(OPEN_OUTPUT, data, &reply);
audio_io_handle_t output = (audio_io_handle_t) reply.readInt32();
ALOGV("openOutput() returned output, %d", output);
- devices = reply.readInt32();
+ devices = (audio_devices_t)reply.readInt32();
if (pDevices) *pDevices = devices;
samplingRate = reply.readInt32();
if (pSamplingRate) *pSamplingRate = samplingRate;
format = (audio_format_t) reply.readInt32();
if (pFormat) *pFormat = format;
- channels = reply.readInt32();
- if (pChannels) *pChannels = channels;
+ channelMask = (audio_channel_mask_t)reply.readInt32();
+ if (pChannelMask) *pChannelMask = channelMask;
latency = reply.readInt32();
if (pLatencyMs) *pLatencyMs = latency;
return output;
@@ -430,34 +433,34 @@ public:
return reply.readInt32();
}
- 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)
{
Parcel data, reply;
- uint32_t devices = pDevices ? *pDevices : 0;
+ audio_devices_t devices = pDevices ? *pDevices : (audio_devices_t)0;
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 : (audio_channel_mask_t)0;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(module);
data.writeInt32(devices);
data.writeInt32(samplingRate);
data.writeInt32(format);
- data.writeInt32(channels);
- data.writeInt32((int32_t) acoustics);
+ data.writeInt32(channelMask);
remote()->transact(OPEN_INPUT, data, &reply);
audio_io_handle_t input = (audio_io_handle_t) reply.readInt32();
- devices = reply.readInt32();
+ devices = (audio_devices_t)reply.readInt32();
if (pDevices) *pDevices = devices;
samplingRate = reply.readInt32();
if (pSamplingRate) *pSamplingRate = samplingRate;
format = (audio_format_t) reply.readInt32();
if (pFormat) *pFormat = format;
- channels = reply.readInt32();
- if (pChannels) *pChannels = channels;
+ channelMask = (audio_channel_mask_t)reply.readInt32();
+ if (pChannelMask) *pChannelMask = channelMask;
return input;
}
@@ -668,6 +671,15 @@ public:
remote()->transact(MOVE_EFFECTS, data, &reply);
return reply.readInt32();
}
+
+ virtual audio_module_handle_t loadHwModule(const char *name)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeCString(name);
+ remote()->transact(LOAD_HW_MODULE, data, &reply);
+ return (audio_module_handle_t) reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -837,24 +849,26 @@ status_t BnAudioFlinger::onTransact(
} break;
case OPEN_OUTPUT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- uint32_t devices = data.readInt32();
+ audio_module_handle_t module = (audio_module_handle_t)data.readInt32();
+ audio_devices_t devices = (audio_devices_t)data.readInt32();
uint32_t samplingRate = data.readInt32();
audio_format_t format = (audio_format_t) data.readInt32();
- uint32_t channels = data.readInt32();
+ audio_channel_mask_t channelMask = (audio_channel_mask_t)data.readInt32();
uint32_t latency = data.readInt32();
audio_policy_output_flags_t flags = (audio_policy_output_flags_t) data.readInt32();
- audio_io_handle_t output = openOutput(&devices,
- &samplingRate,
- &format,
- &channels,
- &latency,
- flags);
+ audio_io_handle_t output = openOutput(module,
+ &devices,
+ &samplingRate,
+ &format,
+ &channelMask,
+ &latency,
+ flags);
ALOGV("OPEN_OUTPUT output, %p", output);
reply->writeInt32((int32_t) output);
reply->writeInt32(devices);
reply->writeInt32(samplingRate);
reply->writeInt32(format);
- reply->writeInt32(channels);
+ reply->writeInt32(channelMask);
reply->writeInt32(latency);
return NO_ERROR;
} break;
@@ -882,22 +896,22 @@ status_t BnAudioFlinger::onTransact(
} break;
case OPEN_INPUT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- uint32_t devices = data.readInt32();
+ audio_module_handle_t module = (audio_module_handle_t)data.readInt32();
+ audio_devices_t devices = (audio_devices_t)data.readInt32();
uint32_t samplingRate = data.readInt32();
audio_format_t format = (audio_format_t) data.readInt32();
- uint32_t channels = data.readInt32();
- audio_in_acoustics_t acoustics = (audio_in_acoustics_t) data.readInt32();
+ audio_channel_mask_t channelMask = (audio_channel_mask_t)data.readInt32();
- audio_io_handle_t input = openInput(&devices,
- &samplingRate,
- &format,
- &channels,
- acoustics);
+ audio_io_handle_t input = openInput(module,
+ &devices,
+ &samplingRate,
+ &format,
+ &channelMask);
reply->writeInt32((int32_t) input);
reply->writeInt32(devices);
reply->writeInt32(samplingRate);
reply->writeInt32(format);
- reply->writeInt32(channels);
+ reply->writeInt32(channelMask);
return NO_ERROR;
} break;
case CLOSE_INPUT: {
@@ -1015,6 +1029,11 @@ status_t BnAudioFlinger::onTransact(
reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
return NO_ERROR;
} break;
+ case LOAD_HW_MODULE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(loadHwModule(data.readCString()));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
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>