summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy/managerdefault
diff options
context:
space:
mode:
Diffstat (limited to 'services/audiopolicy/managerdefault')
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.cpp629
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.h108
2 files changed, 458 insertions, 279 deletions
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 67a5c80..35e80f7 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -157,7 +157,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
// outputs must be closed after checkOutputForAllStrategies() is executed
if (!outputs.isEmpty()) {
for (size_t i = 0; i < outputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]);
// close unused outputs after device disconnection or direct outputs that have been
// opened by checkOutputsForDevice() to query dynamic parameters
if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
@@ -176,18 +176,17 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
updateCallRouting(newDevice);
}
for (size_t i = 0; i < mOutputs.size(); i++) {
- audio_io_handle_t output = mOutputs.keyAt(i);
- if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
- audio_devices_t newDevice = getNewOutputDevice(mOutputs.keyAt(i),
- true /*fromCache*/);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) {
+ audio_devices_t newDevice = getNewOutputDevice(desc, true /*fromCache*/);
// do not force device change on duplicated output because if device is 0, it will
// also force a device 0 for the two outputs it is duplicated to which may override
// a valid device selection on those outputs.
- bool force = !mOutputs.valueAt(i)->isDuplicated()
+ bool force = !desc->isDuplicated()
&& (!device_distinguishes_on_address(device)
// always force when disconnecting (a non-duplicated device)
|| (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
- setOutputDevice(output, newDevice, force, 0);
+ setOutputDevice(desc, newDevice, force, 0);
}
}
@@ -349,10 +348,11 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
AUDIO_OUTPUT_FLAG_NONE,
AUDIO_FORMAT_INVALID);
if (output != AUDIO_IO_HANDLE_NONE) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
ALOG_ASSERT(!outputDesc->isDuplicated(),
"updateCallRouting() RX device output is duplicated");
outputDesc->toAudioPortConfig(&patch.sources[1]);
+ patch.sources[1].ext.mix.usecase.stream = AUDIO_STREAM_PATCH;
patch.num_sources = 2;
}
@@ -395,6 +395,7 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
ALOG_ASSERT(!outputDesc->isDuplicated(),
"updateCallRouting() RX device output is duplicated");
outputDesc->toAudioPortConfig(&patch.sources[1]);
+ patch.sources[1].ext.mix.usecase.stream = AUDIO_STREAM_PATCH;
patch.num_sources = 2;
}
@@ -448,13 +449,13 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
checkOutputForAllStrategies();
updateDevicesAndOutputs();
- sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput);
+ sp<SwAudioOutputDescriptor> hwOutputDesc = mPrimaryOutput;
int delayMs = 0;
if (isStateInCall(state)) {
nsecs_t sysTime = systemTime();
for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
// mute media and sonification strategies and delay device switch by the largest
// latency of any output where either strategy is active.
// This avoid sending the ring tone or music tail into the earpiece or headset.
@@ -464,14 +465,14 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
isStrategyActive(desc, STRATEGY_SONIFICATION,
SONIFICATION_HEADSET_MUSIC_DELAY,
sysTime)) &&
- (delayMs < (int)desc->mLatency*2)) {
- delayMs = desc->mLatency*2;
+ (delayMs < (int)desc->latency()*2)) {
+ delayMs = desc->latency()*2;
}
- setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i));
- setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS,
+ setStrategyMute(STRATEGY_MEDIA, true, desc);
+ setStrategyMute(STRATEGY_MEDIA, false, desc, MUTE_TIME_MS,
getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/));
- setStrategyMute(STRATEGY_SONIFICATION, true, mOutputs.keyAt(i));
- setStrategyMute(STRATEGY_SONIFICATION, false, mOutputs.keyAt(i), MUTE_TIME_MS,
+ setStrategyMute(STRATEGY_SONIFICATION, true, desc);
+ setStrategyMute(STRATEGY_SONIFICATION, false, desc, MUTE_TIME_MS,
getDeviceForStrategy(STRATEGY_SONIFICATION, true /*fromCache*/));
}
}
@@ -547,13 +548,13 @@ void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
updateCallRouting(newDevice);
}
for (size_t i = 0; i < mOutputs.size(); i++) {
- audio_io_handle_t output = mOutputs.keyAt(i);
- audio_devices_t newDevice = getNewOutputDevice(output, true /*fromCache*/);
- if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
- setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
+ audio_devices_t newDevice = getNewOutputDevice(outputDesc, true /*fromCache*/);
+ if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
+ setOutputDevice(outputDesc, newDevice, (newDevice != AUDIO_DEVICE_NONE));
}
if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
- applyStreamVolumes(output, newDevice, 0, true);
+ applyStreamVolumes(outputDesc, newDevice, 0, true);
}
}
@@ -621,6 +622,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
audio_format_t format,
audio_channel_mask_t channelMask,
audio_output_flags_t flags,
+ audio_port_handle_t selectedDeviceId,
const audio_offload_info_t *offloadInfo)
{
audio_attributes_t attributes;
@@ -639,7 +641,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
}
stream_type_to_audio_attributes(*stream, &attributes);
}
- sp<AudioOutputDescriptor> desc;
+ sp<SwAudioOutputDescriptor> desc;
if (mPolicyMixes.getOutputForAttr(attributes, desc) == NO_ERROR) {
ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr");
if (!audio_is_linear_pcm(format)) {
@@ -675,6 +677,17 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
if (*output == AUDIO_IO_HANDLE_NONE) {
return INVALID_OPERATION;
}
+
+ // Explicit routing?
+ sp<DeviceDescriptor> deviceDesc;
+
+ for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
+ if (mAvailableOutputDevices[i]->getId() == selectedDeviceId) {
+ deviceDesc = mAvailableOutputDevices[i];
+ break;
+ }
+ }
+ mOutputRoutes.addRoute(session, *stream, deviceDesc);
return NO_ERROR;
}
@@ -699,7 +712,8 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
if (mTestOutputs[mCurOutput] == 0) {
ALOGV("getOutput() opening test output");
- sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL);
+ sp<AudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(NULL,
+ mpClientInterface);
outputDesc->mDevice = mTestDevice;
outputDesc->mLatency = mTestLatencyMs;
outputDesc->mFlags =
@@ -775,10 +789,10 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
}
if (profile != 0) {
- sp<AudioOutputDescriptor> outputDesc = NULL;
+ sp<SwAudioOutputDescriptor> outputDesc = NULL;
for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if (!desc->isDuplicated() && (profile == desc->mProfile)) {
outputDesc = desc;
// reuse direct output if currently open and configured with same parameters
@@ -795,7 +809,7 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
if (outputDesc != NULL) {
closeOutput(outputDesc->mIoHandle);
}
- outputDesc = new AudioOutputDescriptor(profile);
+ outputDesc = new SwAudioOutputDescriptor(profile, mpClientInterface);
outputDesc->mDevice = device;
outputDesc->mLatency = 0;
outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags);
@@ -806,7 +820,7 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
if (offloadInfo != NULL) {
config.offload_info = *offloadInfo;
}
- status = mpClientInterface->openOutput(profile->mModule->mHandle,
+ status = mpClientInterface->openOutput(profile->getModuleHandle(),
&output,
&config,
&outputDesc->mDevice,
@@ -856,7 +870,6 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
}
non_direct_output:
-
// ignoring channel mask due to downmix capability in mixer
// open a non direct output
@@ -874,7 +887,7 @@ non_direct_output:
ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d,"
"format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags);
- ALOGV("getOutput() returns output %d", output);
+ ALOGV(" getOutputForDevice() returns output %d", output);
return output;
}
@@ -902,7 +915,7 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
audio_io_handle_t outputPrimary = 0;
for (size_t i = 0; i < outputs.size(); i++) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
if (!outputDesc->isDuplicated()) {
// if a valid format is specified, skip output if not compatible
if (format != AUDIO_FORMAT_INVALID) {
@@ -941,15 +954,59 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
audio_session_t session)
{
- ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
+ ALOGV("startOutput() output %d, stream %d, session %d",
+ output, stream, session);
ssize_t index = mOutputs.indexOfKey(output);
if (index < 0) {
ALOGW("startOutput() unknown output %d", output);
return BAD_VALUE;
}
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
+
+ audio_devices_t newDevice;
+ if (outputDesc->mPolicyMix != NULL) {
+ newDevice = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ } else {
+ newDevice = AUDIO_DEVICE_NONE;
+ }
+
+ uint32_t delayMs = 0;
+
+ // Routing?
+ mOutputRoutes.incRouteActivity(session);
+
+ status_t status = startSource(outputDesc, stream, newDevice, &delayMs);
+
+ if (status != NO_ERROR) {
+ mOutputRoutes.decRouteActivity(session);
+ }
+ // Automatically enable the remote submix input when output is started on a re routing mix
+ // of type MIX_TYPE_RECORDERS
+ if (audio_is_remote_submix_device(newDevice) && outputDesc->mPolicyMix != NULL &&
+ outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ outputDesc->mPolicyMix->mRegistrationId,
+ "remote-submix");
+ }
+
+ if (delayMs != 0) {
+ usleep(delayMs * 1000);
+ }
+
+ return status;
+}
+
+status_t AudioPolicyManager::startSource(sp<AudioOutputDescriptor> outputDesc,
+ audio_stream_type_t stream,
+ audio_devices_t device,
+ uint32_t *delayMs)
+{
// cannot start playback of STREAM_TTS if any other output is being used
uint32_t beaconMuteLatency = 0;
+
+ *delayMs = 0;
if (stream == AUDIO_STREAM_TTS) {
ALOGV("\t found BEACON stream");
if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
@@ -962,8 +1019,6 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
beaconMuteLatency = handleEventForBeacon(STARTING_OUTPUT);
}
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
-
// increment usage count for this stream on the requested output:
// NOTE that the usage count is the same for duplicated output and hardware output which is
// necessary for a correct control of hardware output routing by startOutput() and stopOutput()
@@ -971,11 +1026,8 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
if (outputDesc->mRefCount[stream] == 1) {
// starting an output being rerouted?
- audio_devices_t newDevice;
- if (outputDesc->mPolicyMix != NULL) {
- newDevice = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
- } else {
- newDevice = getNewOutputDevice(output, false /*fromCache*/);
+ if (device == AUDIO_DEVICE_NONE) {
+ device = getNewOutputDevice(outputDesc, false /*fromCache*/);
}
routing_strategy strategy = getStrategy(stream);
bool shouldWait = (strategy == STRATEGY_SONIFICATION) ||
@@ -991,7 +1043,7 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
// In this case, the audio HAL must receive the new device selection so that it can
// change the device currently selected by the other active output.
if (outputDesc->sharesHwModuleWith(desc) &&
- desc->device() != newDevice) {
+ desc->device() != device) {
force = true;
}
// wait for audio on other active outputs to be presented when starting
@@ -1003,7 +1055,7 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
}
}
}
- uint32_t muteWaitMs = setOutputDevice(output, newDevice, force);
+ uint32_t muteWaitMs = setOutputDevice(outputDesc, device, force);
// handle special case for sonification while in call
if (isInCall()) {
@@ -1012,32 +1064,18 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
// apply volume rules for current stream and device if necessary
checkAndSetVolume(stream,
- mStreams[stream].getVolumeIndex(newDevice),
- output,
- newDevice);
+ mStreams.valueFor(stream).getVolumeIndex(device),
+ outputDesc,
+ device);
// update the outputs if starting an output with a stream that can affect notification
// routing
handleNotificationRoutingForStream(stream);
- // Automatically enable the remote submix input when output is started on a re routing mix
- // of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(newDevice) && outputDesc->mPolicyMix != NULL &&
- outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- outputDesc->mPolicyMix->mRegistrationId,
- "remote-submix");
- }
-
// force reevaluating accessibility routing when ringtone or alarm starts
if (strategy == STRATEGY_SONIFICATION) {
mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
}
-
- if (waitMs > muteWaitMs) {
- usleep((waitMs - muteWaitMs) * 2 * 1000);
- }
}
return NO_ERROR;
}
@@ -1054,8 +1092,32 @@ status_t AudioPolicyManager::stopOutput(audio_io_handle_t output,
return BAD_VALUE;
}
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
+
+ if (outputDesc->mRefCount[stream] == 1) {
+ // Automatically disable the remote submix input when output is stopped on a
+ // re routing mix of type MIX_TYPE_RECORDERS
+ if (audio_is_remote_submix_device(outputDesc->mDevice) &&
+ outputDesc->mPolicyMix != NULL &&
+ outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ outputDesc->mPolicyMix->mRegistrationId,
+ "remote-submix");
+ }
+ }
+
+ // Routing?
+ if (outputDesc->mRefCount[stream] > 0) {
+ mOutputRoutes.decRouteActivity(session);
+ }
+
+ return stopSource(outputDesc, stream);
+}
+status_t AudioPolicyManager::stopSource(sp<AudioOutputDescriptor> outputDesc,
+ audio_stream_type_t stream)
+{
// always handle stream stop, check which stream type is stopping
handleEventForBeacon(stream == AUDIO_STREAM_TTS ? STOPPING_BEACON : STOPPING_OUTPUT);
@@ -1067,41 +1129,31 @@ status_t AudioPolicyManager::stopOutput(audio_io_handle_t output,
if (outputDesc->mRefCount[stream] > 0) {
// decrement usage count of this stream on the output
outputDesc->changeRefCount(stream, -1);
+
// store time at which the stream was stopped - see isStreamActive()
if (outputDesc->mRefCount[stream] == 0) {
- // Automatically disable the remote submix input when output is stopped on a
- // re routing mix of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(outputDesc->mDevice) &&
- outputDesc->mPolicyMix != NULL &&
- outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- outputDesc->mPolicyMix->mRegistrationId,
- "remote-submix");
- }
-
outputDesc->mStopTime[stream] = systemTime();
- audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/);
+ audio_devices_t newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
// delay the device switch by twice the latency because stopOutput() is executed when
// the track stop() command is received and at that time the audio track buffer can
// still contain data that needs to be drained. The latency only covers the audio HAL
// and kernel buffers. Also the latency does not always include additional delay in the
// audio path (audio DSP, CODEC ...)
- setOutputDevice(output, newDevice, false, outputDesc->mLatency*2);
+ setOutputDevice(outputDesc, newDevice, false, outputDesc->latency()*2);
// force restoring the device selection on other active outputs if it differs from the
// one being selected for this output
for (size_t i = 0; i < mOutputs.size(); i++) {
audio_io_handle_t curOutput = mOutputs.keyAt(i);
sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
- if (curOutput != output &&
+ if (desc != outputDesc &&
desc->isActive() &&
outputDesc->sharesHwModuleWith(desc) &&
(newDevice != desc->device())) {
- setOutputDevice(curOutput,
- getNewOutputDevice(curOutput, false /*fromCache*/),
+ setOutputDevice(desc,
+ getNewOutputDevice(desc, false /*fromCache*/),
true,
- outputDesc->mLatency*2);
+ outputDesc->latency()*2);
}
}
// update the outputs if stopping one with a stream that can affect notification routing
@@ -1109,7 +1161,7 @@ status_t AudioPolicyManager::stopOutput(audio_io_handle_t output,
}
return NO_ERROR;
} else {
- ALOGW("stopOutput() refcount is already 0 for output %d", output);
+ ALOGW("stopOutput() refcount is already 0");
return INVALID_OPERATION;
}
}
@@ -1138,7 +1190,10 @@ void AudioPolicyManager::releaseOutput(audio_io_handle_t output,
}
#endif //AUDIO_POLICY_TEST
- sp<AudioOutputDescriptor> desc = mOutputs.valueAt(index);
+ // Routing
+ mOutputRoutes.removeRoute(session);
+
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(index);
if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
if (desc->mDirectOpenCount <= 0) {
ALOGW("releaseOutput() invalid open count %d for output %d",
@@ -1150,8 +1205,9 @@ void AudioPolicyManager::releaseOutput(audio_io_handle_t output,
// If effects where present on the output, audioflinger moved them to the primary
// output by default: move them back to the appropriate output.
audio_io_handle_t dstOutput = getOutputForEffect();
- if (dstOutput != mPrimaryOutput) {
- mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mPrimaryOutput, dstOutput);
+ if (dstOutput != mPrimaryOutput->mIoHandle) {
+ mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX,
+ mPrimaryOutput->mIoHandle, dstOutput);
}
mpClientInterface->onAudioPortListUpdate();
}
@@ -1265,8 +1321,8 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
}
}
- if (profile->mModule->mHandle == 0) {
- ALOGE("getInputForAttr(): HW module %s not opened", profile->mModule->mName);
+ if (profile->getModuleHandle() == 0) {
+ ALOGE("getInputForAttr(): HW module %s not opened", profile->getModuleName());
return NO_INIT;
}
@@ -1275,7 +1331,7 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
config.channel_mask = channelMask;
config.format = format;
- status_t status = mpClientInterface->openInput(profile->mModule->mHandle,
+ status_t status = mpClientInterface->openInput(profile->getModuleHandle(),
input,
&config,
&device,
@@ -1505,8 +1561,8 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
audio_devices_t device)
{
- if ((index < mStreams[stream].getVolumeIndexMin()) ||
- (index > mStreams[stream].getVolumeIndexMax())) {
+ if ((index < mStreams.valueFor(stream).getVolumeIndexMin()) ||
+ (index > mStreams.valueFor(stream).getVolumeIndexMax())) {
return BAD_VALUE;
}
if (!audio_is_output_device(device)) {
@@ -1514,7 +1570,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
}
// Force max volume if stream cannot be muted
- if (!mStreams.canBeMuted(stream)) index = mStreams[stream].getVolumeIndexMax();
+ if (!mStreams.canBeMuted(stream)) index = mStreams.valueFor(stream).getVolumeIndexMax();
ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d",
stream, device, index);
@@ -1543,16 +1599,17 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
}
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
- audio_devices_t curDevice = Volume::getDeviceForVolume(mOutputs.valueAt(i)->device());
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ audio_devices_t curDevice = Volume::getDeviceForVolume(desc->device());
if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & strategyDevice) != 0)) {
- status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
+ status_t volStatus = checkAndSetVolume(stream, index, desc, curDevice);
if (volStatus != NO_ERROR) {
status = volStatus;
}
}
if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)) {
status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY,
- index, mOutputs.keyAt(i), curDevice);
+ index, desc, curDevice);
}
}
return status;
@@ -1575,7 +1632,7 @@ status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream,
}
device = Volume::getDeviceForVolume(device);
- *index = mStreams[stream].getVolumeIndex(device);
+ *index = mStreams.valueFor(stream).getVolumeIndex(device);
ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index);
return NO_ERROR;
}
@@ -1599,7 +1656,7 @@ audio_io_handle_t AudioPolicyManager::selectOutputForEffects(
audio_io_handle_t outputDeepBuffer = 0;
for (size_t i = 0; i < outputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]);
ALOGV("selectOutputForEffects outputs[%zu] flags %x", i, desc->mFlags);
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
outputOffloaded = outputs[i];
@@ -1653,6 +1710,16 @@ status_t AudioPolicyManager::registerEffect(const effect_descriptor_t *desc,
return mEffects.registerEffect(desc, io, strategy, session, id);
}
+bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
+{
+ return mOutputs.isStreamActive(stream, inPastMs);
+}
+
+bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
+{
+ return mOutputs.isStreamActiveRemotely(stream, inPastMs);
+}
+
bool AudioPolicyManager::isSourceActive(audio_source_t source) const
{
for (size_t i = 0; i < mInputs.size(); i++) {
@@ -1803,7 +1870,7 @@ status_t AudioPolicyManager::dump(int fd)
snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
result.append(buffer);
- snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput);
+ snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput->mIoHandle);
result.append(buffer);
snprintf(buffer, SIZE, " Phone state: %d\n", mEngine->getPhoneState());
result.append(buffer);
@@ -2021,7 +2088,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
}
if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
if (outputDesc == NULL) {
ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id);
return BAD_VALUE;
@@ -2069,7 +2136,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
// TODO: reconfigure output format and channels here
ALOGV("createAudioPatch() setting device %08x on output %d",
devices.types(), outputDesc->mIoHandle);
- setOutputDevice(outputDesc->mIoHandle, devices.types(), true, 0, handle);
+ setOutputDevice(outputDesc, devices.types(), true, 0, handle);
index = mAudioPatches.indexOfKey(*handle);
if (index >= 0) {
if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) {
@@ -2163,8 +2230,12 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
}
sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]);
- if (srcDeviceDesc->mModule != sinkDeviceDesc->mModule) {
- // only one sink supported when connected devices across HW modules
+ // create a software bridge in PatchPanel if:
+ // - source and sink devices are on differnt HW modules OR
+ // - audio HAL version is < 3.0
+ if ((srcDeviceDesc->getModuleHandle() != sinkDeviceDesc->getModuleHandle()) ||
+ (srcDeviceDesc->mModule->mHalVersion < AUDIO_DEVICE_API_VERSION_3_0)) {
+ // support only one sink device for now to simplify output selection logic
if (patch->num_sinks > 1) {
return INVALID_OPERATION;
}
@@ -2181,6 +2252,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
return INVALID_OPERATION;
}
outputDesc->toAudioPortConfig(&newPatch.sources[1], &patch->sources[0]);
+ newPatch.sources[1].ext.mix.usecase.stream = AUDIO_STREAM_PATCH;
newPatch.num_sources = 2;
}
}
@@ -2242,14 +2314,14 @@ status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle,
struct audio_patch *patch = &patchDesc->mPatch;
patchDesc->mUid = mUidCached;
if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
if (outputDesc == NULL) {
ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id);
return BAD_VALUE;
}
- setOutputDevice(outputDesc->mIoHandle,
- getNewOutputDevice(outputDesc->mIoHandle, true /*fromCache*/),
+ setOutputDevice(outputDesc,
+ getNewOutputDevice(outputDesc, true /*fromCache*/),
true,
0,
NULL);
@@ -2308,7 +2380,7 @@ status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *
sp<AudioPortConfig> audioPortConfig;
if (config->type == AUDIO_PORT_TYPE_MIX) {
if (config->role == AUDIO_PORT_ROLE_SOURCE) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(config->id);
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(config->id);
if (outputDesc == NULL) {
return BAD_VALUE;
}
@@ -2390,7 +2462,6 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
#ifdef AUDIO_POLICY_TEST
Thread(false),
#endif //AUDIO_POLICY_TEST
- mPrimaryOutput((audio_io_handle_t)0),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
mSpeakerDrcEnabled(false),
@@ -2474,7 +2545,8 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
if ((profileType & outputDeviceTypes) == 0) {
continue;
}
- sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile);
+ sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
+ mpClientInterface);
outputDesc->mDevice = profileType;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -2482,7 +2554,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
config.channel_mask = outputDesc->mChannelMask;
config.format = outputDesc->mFormat;
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = mpClientInterface->openOutput(outProfile->mModule->mHandle,
+ status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
&output,
&config,
&outputDesc->mDevice,
@@ -2510,10 +2582,10 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
}
if (mPrimaryOutput == 0 &&
outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
- mPrimaryOutput = output;
+ mPrimaryOutput = outputDesc;
}
addOutput(output, outputDesc);
- setOutputDevice(output,
+ setOutputDevice(outputDesc,
outputDesc->mDevice,
true);
}
@@ -2558,7 +2630,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
config.channel_mask = inputDesc->mChannelMask;
config.format = inputDesc->mFormat;
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
- status_t status = mpClientInterface->openInput(inProfile->mModule->mHandle,
+ status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(),
&input,
&config,
&inputDesc->mDevice,
@@ -2620,7 +2692,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
if (mPrimaryOutput != 0) {
AudioParameter outputCmd = AudioParameter();
outputCmd.addInt(String8("set_id"), 0);
- mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString());
+ mpClientInterface->setParameters(mPrimaryOutput->mIoHandle, outputCmd.toString());
mTestDevice = AUDIO_DEVICE_OUT_SPEAKER;
mTestSamplingRate = 44100;
@@ -2760,20 +2832,21 @@ bool AudioPolicyManager::threadLoop()
if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) {
param.remove(String8("test_cmd_policy_reopen"));
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput);
- mpClientInterface->closeOutput(mPrimaryOutput);
+ mpClientInterface->closeOutput(mpClientInterface->closeOutput(mPrimaryOutput););
- audio_module_handle_t moduleHandle = outputDesc->mModule->mHandle;
+ audio_module_handle_t moduleHandle = mPrimaryOutput->getModuleHandle();
- removeOutput(mPrimaryOutput);
- sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL);
+ removeOutput(mPrimaryOutput->mIoHandle);
+ sp<SwAudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL,
+ mpClientInterface);
outputDesc->mDevice = AUDIO_DEVICE_OUT_SPEAKER;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = outputDesc->mSamplingRate;
config.channel_mask = outputDesc->mChannelMask;
config.format = outputDesc->mFormat;
+ audio_io_handle_t handle;
status_t status = mpClientInterface->openOutput(moduleHandle,
- &mPrimaryOutput,
+ &handle,
&config,
&outputDesc->mDevice,
String8(""),
@@ -2787,10 +2860,11 @@ bool AudioPolicyManager::threadLoop()
outputDesc->mSamplingRate = config.sample_rate;
outputDesc->mChannelMask = config.channel_mask;
outputDesc->mFormat = config.format;
+ mPrimaryOutput = outputDesc;
AudioParameter outputCmd = AudioParameter();
outputCmd.addInt(String8("set_id"), 0);
- mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString());
- addOutput(mPrimaryOutput, outputDesc);
+ mpClientInterface->setParameters(handle, outputCmd.toString());
+ addOutput(handle, outputDesc);
}
}
@@ -2822,7 +2896,7 @@ int AudioPolicyManager::testOutputIndex(audio_io_handle_t output)
// ---
-void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc)
+void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<SwAudioOutputDescriptor> outputDesc)
{
outputDesc->setIoHandle(output);
mOutputs.add(output, outputDesc);
@@ -2841,7 +2915,7 @@ void AudioPolicyManager::addInput(audio_io_handle_t input, sp<AudioInputDescript
nextAudioPortGeneration();
}
-void AudioPolicyManager::findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/,
+void AudioPolicyManager::findIoHandlesByAddress(sp<SwAudioOutputDescriptor> desc /*in*/,
const audio_devices_t device /*in*/,
const String8 address /*in*/,
SortedVector<audio_io_handle_t>& outputs /*out*/) {
@@ -2860,7 +2934,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
const String8 address)
{
audio_devices_t device = devDesc->type();
- sp<AudioOutputDescriptor> desc;
+ sp<SwAudioOutputDescriptor> desc;
// erase all current sample rates, formats and channel masks
devDesc->clearCapabilities();
@@ -2868,7 +2942,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
// first list already open outputs that can be routed to this device
for (size_t i = 0; i < mOutputs.size(); i++) {
desc = mOutputs.valueAt(i);
- if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) {
+ if (!desc->isDuplicated() && (desc->supportedDevices() & device)) {
if (!device_distinguishes_on_address(device)) {
ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i));
outputs.add(mOutputs.keyAt(i));
@@ -2927,7 +3001,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
ALOGV("opening output for device %08x with params %s profile %p",
device, address.string(), profile.get());
- desc = new AudioOutputDescriptor(profile);
+ desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
desc->mDevice = device;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = desc->mSamplingRate;
@@ -2937,7 +3011,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
config.offload_info.channel_mask = desc->mChannelMask;
config.offload_info.format = desc->mFormat;
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = mpClientInterface->openOutput(profile->mModule->mHandle,
+ status_t status = mpClientInterface->openOutput(profile->getModuleHandle(),
&output,
&config,
&desc->mDevice,
@@ -3007,7 +3081,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
config.offload_info.sample_rate = config.sample_rate;
config.offload_info.channel_mask = config.channel_mask;
config.offload_info.format = config.format;
- status = mpClientInterface->openOutput(profile->mModule->mHandle,
+ status = mpClientInterface->openOutput(profile->getModuleHandle(),
&output,
&config,
&desc->mDevice,
@@ -3040,28 +3114,29 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
// set initial stream volume for device
- applyStreamVolumes(output, device, 0, true);
+ applyStreamVolumes(desc, device, 0, true);
//TODO: configure audio effect output stage here
// open a duplicating output thread for the new output and the primary output
- duplicatedOutput = mpClientInterface->openDuplicateOutput(output,
- mPrimaryOutput);
+ duplicatedOutput =
+ mpClientInterface->openDuplicateOutput(output,
+ mPrimaryOutput->mIoHandle);
if (duplicatedOutput != AUDIO_IO_HANDLE_NONE) {
// add duplicated output descriptor
- sp<AudioOutputDescriptor> dupOutputDesc =
- new AudioOutputDescriptor(NULL);
- dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput);
- dupOutputDesc->mOutput2 = mOutputs.valueFor(output);
+ sp<SwAudioOutputDescriptor> dupOutputDesc =
+ new SwAudioOutputDescriptor(NULL, mpClientInterface);
+ dupOutputDesc->mOutput1 = mPrimaryOutput;
+ dupOutputDesc->mOutput2 = desc;
dupOutputDesc->mSamplingRate = desc->mSamplingRate;
dupOutputDesc->mFormat = desc->mFormat;
dupOutputDesc->mChannelMask = desc->mChannelMask;
dupOutputDesc->mLatency = desc->mLatency;
addOutput(duplicatedOutput, dupOutputDesc);
- applyStreamVolumes(duplicatedOutput, device, 0, true);
+ applyStreamVolumes(dupOutputDesc, device, 0, true);
} else {
ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
- mPrimaryOutput, output);
+ mPrimaryOutput->mIoHandle, output);
mpClientInterface->closeOutput(output);
removeOutput(output);
nextAudioPortGeneration();
@@ -3083,7 +3158,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
if (device_distinguishes_on_address(device)) {
ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)",
device, address.string());
- setOutputDevice(output, device, true/*force*/, 0/*delay*/,
+ setOutputDevice(desc, device, true/*force*/, 0/*delay*/,
NULL/*patch handle*/, address.string());
}
ALOGV("checkOutputsForDevice(): adding output %d", output);
@@ -3101,10 +3176,9 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
if (!desc->isDuplicated()) {
// exact match on device
if (device_distinguishes_on_address(device) &&
- (desc->mProfile->mSupportedDevices.types() == device)) {
+ (desc->supportedDevices() == device)) {
findIoHandlesByAddress(desc, device, address, outputs);
- } else if (!(desc->mProfile->mSupportedDevices.types()
- & mAvailableOutputDevices.types())) {
+ } else if (!(desc->supportedDevices() & mAvailableOutputDevices.types())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
mOutputs.keyAt(i));
outputs.add(mOutputs.keyAt(i));
@@ -3212,7 +3286,7 @@ status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device,
config.channel_mask = desc->mChannelMask;
config.format = desc->mFormat;
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
- status_t status = mpClientInterface->openInput(profile->mModule->mHandle,
+ status_t status = mpClientInterface->openInput(profile->getModuleHandle(),
&input,
&config,
&desc->mDevice,
@@ -3339,7 +3413,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
{
ALOGV("closeOutput(%d)", output);
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc == NULL) {
ALOGW("closeOutput() unknown output %d", output);
return;
@@ -3348,7 +3422,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
// look for duplicated outputs connected to the output being removed.
for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<AudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i);
+ sp<SwAudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i);
if (dupOutputDesc->isDuplicated() &&
(dupOutputDesc->mOutput1 == outputDesc ||
dupOutputDesc->mOutput2 == outputDesc)) {
@@ -3417,8 +3491,9 @@ void AudioPolicyManager::closeInput(audio_io_handle_t input)
mInputs.removeItem(input);
}
-SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_devices_t device,
- AudioOutputCollection openOutputs)
+SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(
+ audio_devices_t device,
+ SwAudioOutputCollection openOutputs)
{
SortedVector<audio_io_handle_t> outputs;
@@ -3459,14 +3534,14 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
// associated with policies in the "before" and "after" output vectors
ALOGVV("checkOutputForStrategy(): policy related outputs");
for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) {
- const sp<AudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i);
+ const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i);
if (desc != 0 && desc->mPolicyMix != NULL) {
srcOutputs.add(desc->mIoHandle);
ALOGVV(" previous outputs: adding %d", desc->mIoHandle);
}
}
for (size_t i = 0 ; i < mOutputs.size() ; i++) {
- const sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if (desc != 0 && desc->mPolicyMix != NULL) {
dstOutputs.add(desc->mIoHandle);
ALOGVV(" new outputs: adding %d", desc->mIoHandle);
@@ -3478,10 +3553,10 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
strategy, srcOutputs[0], dstOutputs[0]);
// mute strategy while moving tracks from one output to another
for (size_t i = 0; i < srcOutputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]);
if (isStrategyActive(desc, strategy)) {
- setStrategyMute(strategy, true, srcOutputs[i]);
- setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice);
+ setStrategyMute(strategy, true, desc);
+ setStrategyMute(strategy, false, desc, MUTE_TIME_MS, newDevice);
}
}
@@ -3578,12 +3653,11 @@ void AudioPolicyManager::checkA2dpSuspend()
}
}
-audio_devices_t AudioPolicyManager::getNewOutputDevice(audio_io_handle_t output, bool fromCache)
+audio_devices_t AudioPolicyManager::getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
+ bool fromCache)
{
audio_devices_t device = AUDIO_DEVICE_NONE;
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
-
ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
@@ -3761,9 +3835,9 @@ uint32_t AudioPolicyManager::setBeaconMute(bool mute) {
ALOGV("\t muting %d", mute);
uint32_t maxLatency = 0;
for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
setStreamMute(AUDIO_STREAM_TTS, mute/*on*/,
- desc->mIoHandle,
+ desc,
0 /*delay*/, AUDIO_DEVICE_NONE);
const uint32_t latency = desc->latency() * 2;
if (latency > maxLatency) {
@@ -3779,6 +3853,21 @@ uint32_t AudioPolicyManager::setBeaconMute(bool mute) {
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
bool fromCache)
{
+ // Routing
+ // see if we have an explicit route
+ // scan the whole RouteMap, for each entry, convert the stream type to a strategy
+ // (getStrategy(stream)).
+ // if the strategy from the stream type in the RouteMap is the same as the argument above,
+ // and activity count is non-zero
+ // the device = the device from the descriptor in the RouteMap, and exit.
+ for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
+ sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
+ routing_strategy strat = getStrategy(route->mStreamType);
+ if (strat == strategy && route->mDeviceDescriptor != 0 /*&& route->mActivityCount != 0*/) {
+ return route->mDeviceDescriptor->type();
+ }
+ }
+
if (fromCache) {
ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
strategy, mDeviceForStrategy[strategy]);
@@ -3812,7 +3901,7 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor>
for (size_t i = 0; i < NUM_STRATEGIES; i++) {
audio_devices_t curDevice = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/);
- curDevice = curDevice & outputDesc->mProfile->mSupportedDevices.types();
+ curDevice = curDevice & outputDesc->supportedDevices();
bool mute = shouldMute && (curDevice & device) && (curDevice != device);
bool doMute = false;
@@ -3831,10 +3920,9 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor>
== AUDIO_DEVICE_NONE) {
continue;
}
- audio_io_handle_t curOutput = mOutputs.keyAt(j);
- ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d",
- mute ? "muting" : "unmuting", i, curDevice, curOutput);
- setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs);
+ ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x)",
+ mute ? "muting" : "unmuting", i, curDevice);
+ setStrategyMute((routing_strategy)i, mute, desc, mute ? 0 : delayMs);
if (isStrategyActive(desc, (routing_strategy)i)) {
if (mute) {
// FIXME: should not need to double latency if volume could be applied
@@ -3859,9 +3947,9 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor>
}
for (size_t i = 0; i < NUM_STRATEGIES; i++) {
if (isStrategyActive(outputDesc, (routing_strategy)i)) {
- setStrategyMute((routing_strategy)i, true, outputDesc->mIoHandle);
+ setStrategyMute((routing_strategy)i, true, outputDesc);
// do tempMute unmute after twice the mute wait time
- setStrategyMute((routing_strategy)i, false, outputDesc->mIoHandle,
+ setStrategyMute((routing_strategy)i, false, outputDesc,
muteWaitMs *2, device);
}
}
@@ -3876,36 +3964,35 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor>
return 0;
}
-uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output,
+uint32_t AudioPolicyManager::setOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
bool force,
int delayMs,
audio_patch_handle_t *patchHandle,
const char* address)
{
- ALOGV("setOutputDevice() output %d device %04x delayMs %d", output, device, delayMs);
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
+ ALOGV("setOutputDevice() device %04x delayMs %d", device, delayMs);
AudioParameter param;
uint32_t muteWaitMs;
if (outputDesc->isDuplicated()) {
- muteWaitMs = setOutputDevice(outputDesc->mOutput1->mIoHandle, device, force, delayMs);
- muteWaitMs += setOutputDevice(outputDesc->mOutput2->mIoHandle, device, force, delayMs);
+ muteWaitMs = setOutputDevice(outputDesc->subOutput1(), device, force, delayMs);
+ muteWaitMs += setOutputDevice(outputDesc->subOutput2(), device, force, delayMs);
return muteWaitMs;
}
// no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current
// output profile
if ((device != AUDIO_DEVICE_NONE) &&
- ((device & outputDesc->mProfile->mSupportedDevices.types()) == 0)) {
+ ((device & outputDesc->supportedDevices()) == 0)) {
return 0;
}
// filter devices according to output selected
- device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices.types());
+ device = (audio_devices_t)(device & outputDesc->supportedDevices());
audio_devices_t prevDevice = outputDesc->mDevice;
- ALOGV("setOutputDevice() prevDevice %04x", prevDevice);
+ ALOGV("setOutputDevice() prevDevice 0x%04x", prevDevice);
if (device != AUDIO_DEVICE_NONE) {
outputDesc->mDevice = device;
@@ -3918,10 +4005,10 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output,
// AND force is not specified
// AND the output is connected by a valid audio patch.
// Doing this check here allows the caller to call setOutputDevice() without conditions
- if ((device == AUDIO_DEVICE_NONE || device == prevDevice) && !force &&
- outputDesc->mPatchHandle != 0) {
- ALOGV("setOutputDevice() setting same device %04x or null device for output %d",
- device, output);
+ if ((device == AUDIO_DEVICE_NONE || device == prevDevice) &&
+ !force &&
+ outputDesc->mPatchHandle != 0) {
+ ALOGV("setOutputDevice() setting same device 0x%04x or null device", device);
return muteWaitMs;
}
@@ -3929,7 +4016,7 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output,
// do the routing
if (device == AUDIO_DEVICE_NONE) {
- resetOutputDevice(output, delayMs, NULL);
+ resetOutputDevice(outputDesc, delayMs, NULL);
} else {
DeviceVector deviceList = (address == NULL) ?
mAvailableOutputDevices.getDevicesFromType(device)
@@ -3996,16 +4083,15 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output,
}
// update stream volumes according to new device
- applyStreamVolumes(output, device, delayMs);
+ applyStreamVolumes(outputDesc, device, delayMs);
return muteWaitMs;
}
-status_t AudioPolicyManager::resetOutputDevice(audio_io_handle_t output,
+status_t AudioPolicyManager::resetOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
int delayMs,
audio_patch_handle_t *patchHandle)
{
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
ssize_t index;
if (patchHandle) {
index = mAudioPatches.indexOfKey(*patchHandle);
@@ -4162,17 +4248,10 @@ audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t input
}
float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
- int index,
- audio_io_handle_t output,
- audio_devices_t device)
+ int index,
+ audio_devices_t device)
{
- float volume = 1.0;
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
-
- if (device == AUDIO_DEVICE_NONE) {
- device = outputDesc->device();
- }
- volume = mEngine->volIndexToAmpl(Volume::getDeviceCategory(device), stream, index);
+ float volumeDb = mEngine->volIndexToDb(Volume::getDeviceCategory(device), stream, index);
// if a headset is connected, apply the following rules to ring tones and notifications
// to avoid sound level bursts in user's ears:
@@ -4190,41 +4269,39 @@ float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
|| ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) &&
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) &&
mStreams.canBeMuted(stream)) {
- volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
+ volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
// when the phone is ringing we must consider that music could have been paused just before
// by the music application and behave as if music was active if the last music track was
// just stopped
if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
mLimitRingtoneVolume) {
audio_devices_t musicDevice = getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/);
- float musicVol = computeVolume(AUDIO_STREAM_MUSIC,
- mStreams[AUDIO_STREAM_MUSIC].getVolumeIndex(musicDevice),
- output,
+ float musicVolDB = computeVolume(AUDIO_STREAM_MUSIC,
+ mStreams.valueFor(AUDIO_STREAM_MUSIC).getVolumeIndex(musicDevice),
musicDevice);
- float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ?
- musicVol : SONIFICATION_HEADSET_VOLUME_MIN;
- if (volume > minVol) {
- volume = minVol;
- ALOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol);
+ float minVolDB = (musicVolDB > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
+ musicVolDB : SONIFICATION_HEADSET_VOLUME_MIN_DB;
+ if (volumeDb > minVolDB) {
+ volumeDb = minVolDB;
+ ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDB, musicVolDB);
}
}
}
- return volume;
+ return volumeDb;
}
status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
- int index,
- audio_io_handle_t output,
- audio_devices_t device,
- int delayMs,
- bool force)
+ int index,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ audio_devices_t device,
+ int delayMs,
+ bool force)
{
-
// do not change actual stream volume if the stream is muted
- if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {
+ if (outputDesc->mMuteCount[stream] != 0) {
ALOGVV("checkAndSetVolume() stream %d muted count %d",
- stream, mOutputs.valueFor(output)->mMuteCount[stream]);
+ stream, outputDesc->mMuteCount[stream]);
return NO_ERROR;
}
audio_policy_forced_cfg_t forceUseForComm =
@@ -4237,45 +4314,28 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
return INVALID_OPERATION;
}
- float volume = computeVolume(stream, index, output, device);
- // unit gain if rerouting to external policy
- if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
- ssize_t index = mOutputs.indexOfKey(output);
- if (index >= 0) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
- if (outputDesc->mPolicyMix != NULL) {
- ALOGV("max gain when rerouting for output=%d", output);
- volume = 1.0f;
- }
- }
-
+ if (device == AUDIO_DEVICE_NONE) {
+ device = outputDesc->device();
}
- // We actually change the volume if:
- // - the float value returned by computeVolume() changed
- // - the force flag is set
- if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
- force) {
- mOutputs.valueFor(output)->mCurVolume[stream] = volume;
- ALOGVV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
- // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is
- // enabled
- if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
- mpClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volume, output, delayMs);
- }
- mpClientInterface->setStreamVolume(stream, volume, output, delayMs);
+
+ float volumeDb = computeVolume(stream, index, device);
+ if (outputDesc->isFixedVolume(device)) {
+ volumeDb = 0.0f;
}
+ outputDesc->setVolume(volumeDb, stream, device, delayMs, force);
+
if (stream == AUDIO_STREAM_VOICE_CALL ||
stream == AUDIO_STREAM_BLUETOOTH_SCO) {
float voiceVolume;
// Force voice volume to max for bluetooth SCO as volume is managed by the headset
if (stream == AUDIO_STREAM_VOICE_CALL) {
- voiceVolume = (float)index/(float)mStreams[stream].getVolumeIndexMax();
+ voiceVolume = (float)index/(float)mStreams.valueFor(stream).getVolumeIndexMax();
} else {
voiceVolume = 1.0;
}
- if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) {
+ if (voiceVolume != mLastVoiceVolume && outputDesc == mPrimaryOutput) {
mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
mLastVoiceVolume = voiceVolume;
}
@@ -4284,20 +4344,20 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
return NO_ERROR;
}
-void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output,
- audio_devices_t device,
- int delayMs,
- bool force)
+void AudioPolicyManager::applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
+ audio_devices_t device,
+ int delayMs,
+ bool force)
{
- ALOGVV("applyStreamVolumes() for output %d and device %x", output, device);
+ ALOGVV("applyStreamVolumes() for device %08x", device);
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
if (stream == AUDIO_STREAM_PATCH) {
continue;
}
checkAndSetVolume((audio_stream_type_t)stream,
- mStreams[stream].getVolumeIndex(device),
- output,
+ mStreams.valueFor((audio_stream_type_t)stream).getVolumeIndex(device),
+ outputDesc,
device,
delayMs,
force);
@@ -4305,10 +4365,10 @@ void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output,
}
void AudioPolicyManager::setStrategyMute(routing_strategy strategy,
- bool on,
- audio_io_handle_t output,
- int delayMs,
- audio_devices_t device)
+ bool on,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ int delayMs,
+ audio_devices_t device)
{
ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
@@ -4316,32 +4376,31 @@ void AudioPolicyManager::setStrategyMute(routing_strategy strategy,
continue;
}
if (getStrategy((audio_stream_type_t)stream) == strategy) {
- setStreamMute((audio_stream_type_t)stream, on, output, delayMs, device);
+ setStreamMute((audio_stream_type_t)stream, on, outputDesc, delayMs, device);
}
}
}
void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
- bool on,
- audio_io_handle_t output,
- int delayMs,
- audio_devices_t device)
+ bool on,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ int delayMs,
+ audio_devices_t device)
{
- const StreamDescriptor &streamDesc = mStreams[stream];
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
+ const StreamDescriptor& streamDesc = mStreams.valueFor(stream);
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->device();
}
- ALOGVV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d device %04x",
- stream, on, output, outputDesc->mMuteCount[stream], device);
+ ALOGVV("setStreamMute() stream %d, mute %d, mMuteCount %d device %04x",
+ stream, on, outputDesc->mMuteCount[stream], device);
if (on) {
if (outputDesc->mMuteCount[stream] == 0) {
if (streamDesc.canBeMuted() &&
((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) ||
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) {
- checkAndSetVolume(stream, 0, output, device, delayMs);
+ checkAndSetVolume(stream, 0, outputDesc, device, delayMs);
}
}
// increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
@@ -4354,7 +4413,7 @@ void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
if (--outputDesc->mMuteCount[stream] == 0) {
checkAndSetVolume(stream,
streamDesc.getVolumeIndex(device),
- output,
+ outputDesc,
device,
delayMs);
}
@@ -4373,7 +4432,7 @@ void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream,
const routing_strategy stream_strategy = getStrategy(stream);
if ((stream_strategy == STRATEGY_SONIFICATION) ||
((stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL))) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput);
+ sp<SwAudioOutputDescriptor> outputDesc = mPrimaryOutput;
ALOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d",
stream, starting, outputDesc->mDevice, stateChange);
if (outputDesc->mRefCount[stream]) {
@@ -4406,6 +4465,70 @@ void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream,
}
}
+// --- SessionRoute class implementation
+void AudioPolicyManager::SessionRoute::log(const char* prefix) {
+ ALOGI("%s[SessionRoute strm:0x%X, sess:0x%X, dev:0x%X refs:%d act:%d",
+ prefix, mStreamType, mSession,
+ mDeviceDescriptor != 0 ? mDeviceDescriptor->type() : AUDIO_DEVICE_NONE,
+ mRefCount, mActivityCount);
+}
+
+// --- SessionRouteMap class implementation
+bool AudioPolicyManager::SessionRouteMap::hasRoute(audio_session_t session)
+{
+ return indexOfKey(session) >= 0 && valueFor(session)->mDeviceDescriptor != 0;
+}
+
+void AudioPolicyManager::SessionRouteMap::addRoute(audio_session_t session,
+ audio_stream_type_t streamType,
+ sp<DeviceDescriptor> deviceDescriptor)
+{
+ sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0;
+ if (route != NULL) {
+ route->mRefCount++;
+ route->mDeviceDescriptor = deviceDescriptor;
+ } else {
+ route = new AudioPolicyManager::SessionRoute(session, streamType, deviceDescriptor);
+ route->mRefCount++;
+ add(session, route);
+ }
+}
+
+void AudioPolicyManager::SessionRouteMap::removeRoute(audio_session_t session)
+{
+ sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0;
+ if (route != 0) {
+ ALOG_ASSERT(route->mRefCount > 0);
+ --route->mRefCount;
+ if (route->mRefCount <= 0) {
+ removeItem(session);
+ }
+ }
+}
+
+int AudioPolicyManager::SessionRouteMap::incRouteActivity(audio_session_t session)
+{
+ sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0;
+ return route != 0 ? ++(route->mActivityCount) : -1;
+}
+
+int AudioPolicyManager::SessionRouteMap::decRouteActivity(audio_session_t session)
+{
+ sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0;
+ if (route != 0 && route->mActivityCount > 0) {
+ return --(route->mActivityCount);
+ } else {
+ return -1;
+ }
+}
+
+void AudioPolicyManager::SessionRouteMap::log(const char* caption) {
+ ALOGI("%s ----", caption);
+ for(size_t index = 0; index < size(); index++) {
+ valueAt(index)->log(" ");
+ }
+}
+
void AudioPolicyManager::defaultAudioPolicyConfig(void)
{
sp<HwModule> module;
@@ -4417,7 +4540,8 @@ void AudioPolicyManager::defaultAudioPolicyConfig(void)
module = new HwModule("primary");
- profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SOURCE, module);
+ profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SOURCE);
+ profile->attach(module);
profile->mSamplingRates.add(44100);
profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
profile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO);
@@ -4425,7 +4549,8 @@ void AudioPolicyManager::defaultAudioPolicyConfig(void)
profile->mFlags = AUDIO_OUTPUT_FLAG_PRIMARY;
module->mOutputProfiles.add(profile);
- profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SINK, module);
+ profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SINK);
+ profile->attach(module);
profile->mSamplingRates.add(8000);
profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
profile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 02b678a..11fd5ff 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -49,8 +49,11 @@ namespace android {
// Attenuation applied to STRATEGY_SONIFICATION streams when a headset is connected: 6dB
#define SONIFICATION_HEADSET_VOLUME_FACTOR 0.5
+#define SONIFICATION_HEADSET_VOLUME_FACTOR_DB (-6)
// Min volume for STRATEGY_SONIFICATION streams when limited by music volume: -36dB
#define SONIFICATION_HEADSET_VOLUME_MIN 0.016
+#define SONIFICATION_HEADSET_VOLUME_MIN_DB (-36)
+
// Time in milliseconds during which we consider that music is still active after a music
// track was stopped - see computeVolume()
#define SONIFICATION_HEADSET_MUSIC_DELAY 5000
@@ -110,6 +113,7 @@ public:
audio_format_t format,
audio_channel_mask_t channelMask,
audio_output_flags_t flags,
+ audio_port_handle_t selectedDeviceId,
const audio_offload_info_t *offloadInfo);
virtual status_t startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
@@ -172,19 +176,15 @@ public:
return mEffects.setEffectEnabled(id, enabled);
}
- virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const
- {
- return mOutputs.isStreamActive(stream, inPastMs);
- }
+ virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
// return whether a stream is playing remotely, override to change the definition of
// local/remote playback, used for instance by notification manager to not make
// media players lose audio focus when not playing locally
// For the base implementation, "remotely" means playing during screen mirroring which
// uses an output for playback with a non-empty, non "0" address.
- virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const
- {
- return mOutputs.isStreamActiveRemotely(stream, inPastMs);
- }
+ virtual bool isStreamActiveRemotely(audio_stream_type_t stream,
+ uint32_t inPastMs = 0) const;
+
virtual bool isSourceActive(audio_source_t source) const;
virtual status_t dump(int fd);
@@ -227,6 +227,46 @@ public:
// return the strategy corresponding to a given stream type
routing_strategy getStrategy(audio_stream_type_t stream) const;
+protected:
+ class SessionRoute : public RefBase
+ {
+ public:
+ friend class SessionRouteMap;
+ SessionRoute(audio_session_t session,
+ audio_stream_type_t streamType,
+ sp<DeviceDescriptor> deviceDescriptor)
+ : mSession(session),
+ mStreamType(streamType),
+ mDeviceDescriptor(deviceDescriptor),
+ mRefCount(0),
+ mActivityCount(0) {}
+
+ audio_session_t mSession;
+ audio_stream_type_t mStreamType;
+
+ sp<DeviceDescriptor> mDeviceDescriptor;
+
+ // "reference" counting
+ int mRefCount; // +/- on references
+ int mActivityCount; // +/- on start/stop
+
+ void log(const char* prefix);
+ };
+
+ class SessionRouteMap: public KeyedVector<audio_session_t, sp<SessionRoute>>
+ {
+ public:
+ bool hasRoute(audio_session_t session);
+ void addRoute(audio_session_t session, audio_stream_type_t streamType,
+ sp<DeviceDescriptor> deviceDescriptor);
+ void removeRoute(audio_session_t session);
+
+ int incRouteActivity(audio_session_t session);
+ int decRouteActivity(audio_session_t session);
+
+ void log(const char* caption);
+ };
+
// From AudioPolicyManagerObserver
virtual const AudioPatchCollection &getAudioPatches() const
{
@@ -240,7 +280,7 @@ public:
{
return mPolicyMixes;
}
- virtual const AudioOutputCollection &getOutputs() const
+ virtual const SwAudioOutputCollection &getOutputs() const
{
return mOutputs;
}
@@ -265,7 +305,7 @@ public:
return mDefaultOutputDevice;
}
protected:
- void addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc);
+ void addOutput(audio_io_handle_t output, sp<SwAudioOutputDescriptor> outputDesc);
void removeOutput(audio_io_handle_t output);
void addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc);
@@ -288,13 +328,13 @@ protected:
// change the route of the specified output. Returns the number of ms we have slept to
// allow new routing to take effect in certain cases.
- virtual uint32_t setOutputDevice(audio_io_handle_t output,
+ virtual uint32_t setOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
bool force = false,
int delayMs = 0,
audio_patch_handle_t *patchHandle = NULL,
const char* address = NULL);
- status_t resetOutputDevice(audio_io_handle_t output,
+ status_t resetOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
audio_patch_handle_t *patchHandle = NULL);
status_t setInputDevice(audio_io_handle_t input,
@@ -309,29 +349,31 @@ protected:
// compute the actual volume for a given stream according to the requested index and a particular
// device
- virtual float computeVolume(audio_stream_type_t stream, int index,
- audio_io_handle_t output, audio_devices_t device);
+ virtual float computeVolume(audio_stream_type_t stream,
+ int index,
+ audio_devices_t device);
// check that volume change is permitted, compute and send new volume to audio hardware
virtual status_t checkAndSetVolume(audio_stream_type_t stream, int index,
- audio_io_handle_t output,
+ const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
int delayMs = 0, bool force = false);
// apply all stream volumes to the specified output and device
- void applyStreamVolumes(audio_io_handle_t output, audio_devices_t device, int delayMs = 0, bool force = false);
+ void applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
+ audio_devices_t device, int delayMs = 0, bool force = false);
// Mute or unmute all streams handled by the specified strategy on the specified output
void setStrategyMute(routing_strategy strategy,
bool on,
- audio_io_handle_t output,
+ const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
audio_devices_t device = (audio_devices_t)0);
// Mute or unmute the stream on the specified output
void setStreamMute(audio_stream_type_t stream,
bool on,
- audio_io_handle_t output,
+ const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
audio_devices_t device = (audio_devices_t)0);
@@ -384,7 +426,8 @@ protected:
// must be called every time a condition that affects the device choice for a given output is
// changed: connected device, phone state, force use, output start, output stop..
// see getDeviceForStrategy() for the use of fromCache parameter
- audio_devices_t getNewOutputDevice(audio_io_handle_t output, bool fromCache);
+ audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
+ bool fromCache);
// updates cache of device used by all strategies (mDeviceForStrategy[])
// must be called every time a condition that affects the device choice for a given strategy is
@@ -412,7 +455,7 @@ protected:
#endif //AUDIO_POLICY_TEST
SortedVector<audio_io_handle_t> getOutputsForDevice(audio_devices_t device,
- AudioOutputCollection openOutputs);
+ SwAudioOutputCollection openOutputs);
bool vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
SortedVector<audio_io_handle_t>& outputs2);
@@ -453,28 +496,39 @@ protected:
audio_devices_t availablePrimaryOutputDevices() const
{
- return mOutputs.getSupportedDevices(mPrimaryOutput) & mAvailableOutputDevices.types();
+ return mPrimaryOutput->supportedDevices() & mAvailableOutputDevices.types();
}
audio_devices_t availablePrimaryInputDevices() const
{
- return mAvailableInputDevices.getDevicesFromHwModule(
- mOutputs.valueFor(mPrimaryOutput)->getModuleHandle());
+ return mAvailableInputDevices.getDevicesFromHwModule(mPrimaryOutput->getModuleHandle());
}
void updateCallRouting(audio_devices_t rxDevice, int delayMs = 0);
+ status_t startSource(sp<AudioOutputDescriptor> outputDesc,
+ audio_stream_type_t stream,
+ audio_devices_t device,
+ uint32_t *delayMs);
+ status_t stopSource(sp<AudioOutputDescriptor> outputDesc,
+ audio_stream_type_t stream);
+
uid_t mUidCached;
AudioPolicyClientInterface *mpClientInterface; // audio policy client interface
- audio_io_handle_t mPrimaryOutput; // primary output handle
+ sp<SwAudioOutputDescriptor> mPrimaryOutput; // primary output descriptor
// list of descriptors for outputs currently opened
- AudioOutputCollection mOutputs;
+
+ SwAudioOutputCollection mOutputs;
// copy of mOutputs before setDeviceConnectionState() opens new outputs
// reset to mOutputs when updateDevicesAndOutputs() is called.
- AudioOutputCollection mPreviousOutputs;
+ SwAudioOutputCollection mPreviousOutputs;
AudioInputCollection mInputs; // list of input descriptors
+
DeviceVector mAvailableOutputDevices; // all available output devices
DeviceVector mAvailableInputDevices; // all available input devices
+ SessionRouteMap mOutputRoutes;
+ SessionRouteMap mInputRoutes;
+
StreamDescriptorCollection mStreams; // stream descriptors for volume control
bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected
audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
@@ -539,7 +593,7 @@ private:
// in mProfile->mSupportedDevices) matches the device whose address is to be matched.
// see deviceDistinguishesOnAddress(audio_devices_t) for whether the device type is one
// where addresses are used to distinguish between one connected device and another.
- void findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/,
+ void findIoHandlesByAddress(sp<SwAudioOutputDescriptor> desc /*in*/,
const audio_devices_t device /*in*/,
const String8 address /*in*/,
SortedVector<audio_io_handle_t>& outputs /*out*/);