summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy/AudioPolicyManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audiopolicy/AudioPolicyManager.cpp')
-rw-r--r--services/audiopolicy/AudioPolicyManager.cpp141
1 files changed, 94 insertions, 47 deletions
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index e449863..737cacd 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -1055,13 +1055,14 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
uint32_t samplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
- audio_in_acoustics_t acoustics)
+ audio_in_acoustics_t acoustics,
+ audio_input_flags_t flags)
{
- audio_io_handle_t input = 0;
- audio_devices_t device = getDeviceForInputSource(inputSource);
+ ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, acoustics %x, "
+ "flags %#x",
+ inputSource, samplingRate, format, channelMask, acoustics, flags);
- ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, acoustics %x",
- inputSource, samplingRate, format, channelMask, acoustics);
+ audio_devices_t device = getDeviceForInputSource(inputSource);
if (device == AUDIO_DEVICE_NONE) {
ALOGW("getInput() could not find device for inputSource %d", inputSource);
@@ -1069,7 +1070,7 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
}
// adapt channel selection to input source
- switch(inputSource) {
+ switch (inputSource) {
case AUDIO_SOURCE_VOICE_UPLINK:
channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
break;
@@ -1086,11 +1087,12 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
sp<IOProfile> profile = getInputProfile(device,
samplingRate,
format,
- channelMask);
+ channelMask,
+ flags);
if (profile == 0) {
- ALOGW("getInput() could not find profile for device %04x, samplingRate %d, format %d, "
- "channelMask %04x",
- device, samplingRate, format, channelMask);
+ ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, "
+ "channelMask 0x%X, flags %#x",
+ device, samplingRate, format, channelMask, flags);
return 0;
}
@@ -1107,19 +1109,21 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
inputDesc->mFormat = format;
inputDesc->mChannelMask = channelMask;
inputDesc->mRefCount = 0;
- input = mpClientInterface->openInput(profile->mModule->mHandle,
+ inputDesc->mOpenRefCount = 1;
+
+ audio_io_handle_t input = mpClientInterface->openInput(profile->mModule->mHandle,
&inputDesc->mDevice,
&inputDesc->mSamplingRate,
&inputDesc->mFormat,
&inputDesc->mChannelMask,
- AUDIO_INPUT_FLAG_FAST /*FIXME*/);
+ flags);
// only accept input with the exact requested set of parameters
if (input == 0 ||
(samplingRate != inputDesc->mSamplingRate) ||
(format != inputDesc->mFormat) ||
(channelMask != inputDesc->mChannelMask)) {
- ALOGI("getInput() failed opening input: samplingRate %d, format %d, channelMask %x",
+ ALOGW("getInput() failed opening input: samplingRate %d, format %d, channelMask %x",
samplingRate, format, channelMask);
if (input != 0) {
mpClientInterface->closeInput(input);
@@ -1141,37 +1145,41 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input)
}
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
-#ifdef AUDIO_POLICY_TEST
- if (mTestInput == 0)
-#endif //AUDIO_POLICY_TEST
- {
- // refuse 2 active AudioRecord clients at the same time except if the active input
- // uses AUDIO_SOURCE_HOTWORD in which case it is closed.
+ // virtual input devices are compatible with other input devices
+ if (!isVirtualInputDevice(inputDesc->mDevice)) {
+
+ // for a non-virtual input device, check if there is another (non-virtual) active input
audio_io_handle_t activeInput = getActiveInput();
- if (!isVirtualInputDevice(inputDesc->mDevice) && activeInput != 0) {
+ if (activeInput != 0 && activeInput != input) {
+
+ // If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
+ // otherwise the active input continues and the new input cannot be started.
sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) {
- ALOGW("startInput() preempting already started low-priority input %d", activeInput);
+ ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput);
stopInput(activeInput);
releaseInput(activeInput);
} else {
- ALOGW("startInput() input %d failed: other input already started", input);
+ ALOGE("startInput(%d) failed: other input %d already started", input, activeInput);
return INVALID_OPERATION;
}
}
}
- setInputDevice(input, getNewInputDevice(input), true /* force */);
+ if (inputDesc->mRefCount == 0) {
+ setInputDevice(input, getNewInputDevice(input), true /* force */);
- // automatically enable the remote submix output when input is started
- if (audio_is_remote_submix_device(inputDesc->mDevice)) {
- setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS);
+ // Automatically enable the remote submix output when input is started.
+ // For remote submix (a virtual device), we open only one input per capture request.
+ if (audio_is_remote_submix_device(inputDesc->mDevice)) {
+ setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS);
+ }
}
ALOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
- inputDesc->mRefCount = 1;
+ inputDesc->mRefCount++;
return NO_ERROR;
}
@@ -1188,7 +1196,11 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input)
if (inputDesc->mRefCount == 0) {
ALOGW("stopInput() input %d already stopped", input);
return INVALID_OPERATION;
- } else {
+ }
+
+ inputDesc->mRefCount--;
+ if (inputDesc->mRefCount == 0) {
+
// automatically disable the remote submix output when input is stopped
if (audio_is_remote_submix_device(inputDesc->mDevice)) {
setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -1196,9 +1208,8 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input)
}
resetInputDevice(input);
- inputDesc->mRefCount = 0;
- return NO_ERROR;
}
+ return NO_ERROR;
}
void AudioPolicyManager::releaseInput(audio_io_handle_t input)
@@ -1209,6 +1220,18 @@ void AudioPolicyManager::releaseInput(audio_io_handle_t input)
ALOGW("releaseInput() releasing unknown input %d", input);
return;
}
+ sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
+ ALOG_ASSERT(inputDesc != 0);
+ if (inputDesc->mOpenRefCount == 0) {
+ ALOGW("releaseInput() invalid open ref count %d", inputDesc->mOpenRefCount);
+ return;
+ }
+ inputDesc->mOpenRefCount--;
+ if (inputDesc->mOpenRefCount > 0) {
+ ALOGV("releaseInput() exit > 0");
+ return;
+ }
+
mpClientInterface->closeInput(input);
mInputs.removeItem(input);
nextAudioPortGeneration();
@@ -1874,7 +1897,8 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
patch->sources[0].sample_rate,
patch->sources[0].format,
patch->sources[0].channel_mask,
- AUDIO_OUTPUT_FLAG_NONE)) {
+ AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
+ ALOGV("createAudioPatch() profile not supported");
return INVALID_OPERATION;
}
// TODO: reconfigure output format and channels here
@@ -1919,7 +1943,10 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
patch->sinks[0].sample_rate,
patch->sinks[0].format,
patch->sinks[0].channel_mask,
- AUDIO_OUTPUT_FLAG_NONE)) {
+ // FIXME for the parameter type,
+ // and the NONE
+ (audio_output_flags_t)
+ AUDIO_INPUT_FLAG_NONE)) {
return INVALID_OPERATION;
}
// TODO: reconfigure output format and channels here
@@ -1963,9 +1990,20 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
srcDeviceDesc->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]);
sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[0], &patch->sinks[0]);
- // TODO: add support for devices on different HW modules
if (srcDeviceDesc->mModule != sinkDeviceDesc->mModule) {
- return INVALID_OPERATION;
+ SortedVector<audio_io_handle_t> outputs =
+ getOutputsForDevice(sinkDeviceDesc->mDeviceType, mOutputs);
+ // if the sink device is reachable via an opened output stream, request to go via
+ // this output stream by adding a second source to the patch description
+ audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE);
+ if (output != AUDIO_IO_HANDLE_NONE) {
+ sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
+ if (outputDesc->isDuplicated()) {
+ return INVALID_OPERATION;
+ }
+ outputDesc->toAudioPortConfig(&newPatch.sources[1], &patch->sources[0]);
+ newPatch.num_sources = 2;
+ }
}
// TODO: check from routing capabilities in config file and other conflicting patches
@@ -2270,12 +2308,17 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
continue;
}
- audio_devices_t profileTypes = outProfile->mSupportedDevices.types();
- if ((profileTypes & outputDeviceTypes) &&
+ audio_devices_t profileType = outProfile->mSupportedDevices.types();
+ if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) {
+ profileType = mDefaultOutputDevice->mDeviceType;
+ } else {
+ profileType = outProfile->mSupportedDevices[0]->mDeviceType;
+ }
+ if ((profileType & outputDeviceTypes) &&
((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile);
- outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice->mDeviceType & profileTypes);
+ outputDesc->mDevice = profileType;
audio_io_handle_t output = mpClientInterface->openOutput(
outProfile->mModule->mHandle,
&outputDesc->mDevice,
@@ -2304,7 +2347,6 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
mPrimaryOutput = output;
}
addOutput(output, outputDesc);
- ALOGI("CSTOR setOutputDevice %08x", outputDesc->mDevice);
setOutputDevice(output,
outputDesc->mDevice,
true);
@@ -2322,19 +2364,19 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
continue;
}
- audio_devices_t profileTypes = inProfile->mSupportedDevices.types();
- if (profileTypes & inputDeviceTypes) {
+ audio_devices_t profileType = inProfile->mSupportedDevices[0]->mDeviceType;
+ if (profileType & inputDeviceTypes) {
sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile);
inputDesc->mInputSource = AUDIO_SOURCE_MIC;
- inputDesc->mDevice = inProfile->mSupportedDevices[0]->mDeviceType;
+ inputDesc->mDevice = profileType;
audio_io_handle_t input = mpClientInterface->openInput(
inProfile->mModule->mHandle,
&inputDesc->mDevice,
&inputDesc->mSamplingRate,
&inputDesc->mFormat,
&inputDesc->mChannelMask,
- AUDIO_INPUT_FLAG_FAST /*FIXME*/);
+ AUDIO_INPUT_FLAG_NONE /*FIXME*/);
if (input != 0) {
for (size_t k = 0; k < inProfile->mSupportedDevices.size(); k++) {
@@ -2659,7 +2701,8 @@ status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
continue;
}
- ALOGV("opening output for device %08x with params %s", device, address.string());
+ ALOGV("opening output for device %08x with params %s profile %p",
+ device, address.string(), profile.get());
desc = new AudioOutputDescriptor(profile);
desc->mDevice = device;
audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
@@ -2901,7 +2944,7 @@ status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device,
&desc->mSamplingRate,
&desc->mFormat,
&desc->mChannelMask,
- AUDIO_INPUT_FLAG_FAST /*FIXME*/);
+ AUDIO_INPUT_FLAG_NONE /*FIXME*/);
if (input != 0) {
if (!address.isEmpty()) {
@@ -3908,7 +3951,8 @@ status_t AudioPolicyManager::resetInputDevice(audio_io_handle_t input,
sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device,
uint32_t samplingRate,
audio_format_t format,
- audio_channel_mask_t channelMask)
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags __unused)
{
// Choose an input profile based on the requested capture parameters: select the first available
// profile supporting all requested parameters.
@@ -4763,6 +4807,9 @@ status_t AudioPolicyManager::AudioInputDescriptor::dump(int fd)
result.append(buffer);
snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
result.append(buffer);
+ snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount);
+ result.append(buffer);
+
write(fd, result.string(), result.size());
return NO_ERROR;
@@ -5942,7 +5989,7 @@ void AudioPolicyManager::DeviceDescriptor::toAudioPortConfig(
void AudioPolicyManager::DeviceDescriptor::toAudioPort(struct audio_port *port) const
{
- ALOGV("DeviceVector::toAudioPort() handle %d type %x", mId, mDeviceType);
+ ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType);
AudioPort::toAudioPort(port);
port->id = mId;
toAudioPortConfig(&port->active_config);