Merge "policy_hal: fix CTS concurrent audio playback"
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 26064c9..8e0d401 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -331,8 +331,6 @@
// handle input devices
if (audio_is_input_device(deviceType)) {
- SortedVector <audio_io_handle_t> inputs;
-
ssize_t index = mAvailableInputDevices.indexOf(device);
switch (state)
{
@@ -353,7 +351,7 @@
// parameters on newly connected devices (instead of opening the inputs...)
broadcastDeviceConnectionState(device, state);
- if (checkInputsForDevice(device, state, inputs) != NO_ERROR) {
+ if (checkInputsForDevice(device, state) != NO_ERROR) {
broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
mHwModules.cleanUpForDevice(device);
@@ -382,7 +380,7 @@
// Set Disconnect to HALs
broadcastDeviceConnectionState(device, state);
- checkInputsForDevice(device, state, inputs);
+ checkInputsForDevice(device, state);
mAvailableInputDevices.remove(device);
} break;
@@ -395,7 +393,7 @@
// Propagate device availability to Engine
setEngineDeviceConnectionState(device, state);
- closeAllInputs();
+ checkCloseInputs();
/*audio policy: fix call volume over USB*/
// As the input device list can impact the output device selection, update
// getDeviceForStrategy() cache
@@ -1745,82 +1743,80 @@
goto non_direct_output;
}
- if ((*flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0 || output != AUDIO_IO_HANDLE_NONE) {
- sp<SwAudioOutputDescriptor> outputDesc = NULL;
- // if multiple concurrent offload decode is supported
- // do no check for reuse and also don't close previous output if its offload
- // previous output will be closed during track destruction
- if (!mApmConfigs->isAudioMultipleOffloadEnable() &&
- ((*flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
- for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- if (!desc->isDuplicated() && (profile == desc->mProfile)) {
- outputDesc = desc;
- // reuse direct output if currently open by the same client
- // and configured with same parameters
- if ((config->sample_rate == desc->mSamplingRate) &&
- audio_formats_match(config->format, desc->mFormat) &&
- (channelMask == desc->mChannelMask) &&
- (session == desc->mDirectClientSession)) {
- desc->mDirectOpenCount++;
- ALOGV("getOutputForDevice() reusing direct output %d for session %d",
- mOutputs.keyAt(i), session);
- return mOutputs.keyAt(i);
- }
- }
- if (outputDesc != NULL) {
- if ((((*flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_pcm_already_in_use) ||
- ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
- compress_offload_already_in_use)) &&
- session != outputDesc->mDirectClientSession) {
- ALOGV("getOutput() do not reuse direct pcm output because current client (%d) "
- "is not the same as requesting client (%d) for different output conf",
- outputDesc->mDirectClientSession, session);
- goto non_direct_output;
- }
- closeOutput(outputDesc->mIoHandle);
+ sp<SwAudioOutputDescriptor> outputDesc = NULL;
+ // if multiple concurrent offload decode is supported
+ // do no check for reuse and also don't close previous output if its offload
+ // previous output will be closed during track destruction
+ if (!mApmConfigs->isAudioMultipleOffloadEnable() &&
+ ((*flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ if (!desc->isDuplicated() && (profile == desc->mProfile)) {
+ outputDesc = desc;
+ // reuse direct output if currently open by the same client
+ // and configured with same parameters
+ if ((config->sample_rate == desc->mSamplingRate) &&
+ audio_formats_match(config->format, desc->mFormat) &&
+ (channelMask == desc->mChannelMask) &&
+ (session == desc->mDirectClientSession)) {
+ desc->mDirectOpenCount++;
+ ALOGV("getOutputForDevice() reusing direct output %d for session %d",
+ mOutputs.keyAt(i), session);
+ return mOutputs.keyAt(i);
}
}
- if (!profile->canOpenNewIo()) {
- goto non_direct_output;
+ }
+ if (outputDesc != NULL) {
+ if ((((*flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_pcm_already_in_use) ||
+ ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
+ compress_offload_already_in_use)) &&
+ session != outputDesc->mDirectClientSession) {
+ ALOGV("getOutput() do not reuse direct pcm output because current client (%d) "
+ "is not the same as requesting client (%d) for different output conf",
+ outputDesc->mDirectClientSession, session);
+ goto non_direct_output;
}
-
- outputDesc =
- new SwAudioOutputDescriptor(profile, mpClientInterface);
- DeviceVector outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(devices.types());
- String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->address()
- : String8("");
- status = outputDesc->open(config, devices, stream, *flags, &output);
-
- // only accept an output with the requested parameters
- if (status != NO_ERROR ||
- (config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
- (config->format != AUDIO_FORMAT_DEFAULT &&
- !audio_formats_match(config->format, outputDesc->mFormat)) ||
- (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
- ALOGV("getOutputForDevice() failed opening direct output: output %d sample rate %d %d,"
- "format %d %d, channel mask %04x %04x", output, config->sample_rate,
- outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
- channelMask, outputDesc->mChannelMask);
- if (output != AUDIO_IO_HANDLE_NONE) {
- outputDesc->close();
- }
- // fall back to mixer output if possible when the direct output could not be open
- if (audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX) {
- goto non_direct_output;
- }
- return AUDIO_IO_HANDLE_NONE;
- }
- outputDesc->mDirectOpenCount = 1;
- outputDesc->mDirectClientSession = session;
-
- addOutput(output, outputDesc);
- mPreviousOutputs = mOutputs;
- ALOGV("getOutputForDevice() returns new direct output %d", output);
- mpClientInterface->onAudioPortListUpdate();
- return output;
+ closeOutput(outputDesc->mIoHandle);
}
}
+ if (!profile->canOpenNewIo()) {
+ goto non_direct_output;
+ }
+
+ outputDesc =
+ new SwAudioOutputDescriptor(profile, mpClientInterface);
+ DeviceVector outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(devices.types());
+ String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->address()
+ : String8("");
+ status = outputDesc->open(config, devices, stream, *flags, &output);
+
+ // only accept an output with the requested parameters
+ if (status != NO_ERROR ||
+ (config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
+ (config->format != AUDIO_FORMAT_DEFAULT &&
+ !audio_formats_match(config->format, outputDesc->mFormat)) ||
+ (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
+ ALOGV("getOutputForDevice() failed opening direct output: output %d sample rate %d %d,"
+ "format %d %d, channel mask %04x %04x", output, config->sample_rate,
+ outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
+ channelMask, outputDesc->mChannelMask);
+ if (output != AUDIO_IO_HANDLE_NONE) {
+ outputDesc->close();
+ }
+ // fall back to mixer output if possible when the direct output could not be open
+ if (audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX) {
+ goto non_direct_output;
+ }
+ return AUDIO_IO_HANDLE_NONE;
+ }
+ outputDesc->mDirectOpenCount = 1;
+ outputDesc->mDirectClientSession = session;
+
+ addOutput(output, outputDesc);
+ mPreviousOutputs = mOutputs;
+ ALOGV("getOutputForDevice() returns new direct output %d", output);
+ mpClientInterface->onAudioPortListUpdate();
+ return output;
}
non_direct_output:
@@ -1867,6 +1863,7 @@
status_t AudioPolicyManagerCustom::getInputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *input,
+ audio_unique_id_t riid,
audio_session_t session,
uid_t uid,
const audio_config_base_t *config,
@@ -1932,6 +1929,7 @@
return AudioPolicyManager::getInputForAttr(attr,
input,
+ riid,
session,
uid,
config,
@@ -1967,6 +1965,11 @@
audio_io_handle_t input = inputDesc->mIoHandle;
sp<RecordClientDescriptor> client = inputDesc->getClient(portId);
+ if (client == NULL) {
+ ALOGW("%s invalid client desc for %d", __FUNCTION__, portId);
+ return BAD_VALUE;
+ }
+
if (client->active()) {
ALOGW("%s input %d client %d already started", __FUNCTION__, input, client->portId());
return INVALID_OPERATION;
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 5a8a907..61f9821 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -96,6 +96,7 @@
virtual status_t getInputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *input,
+ audio_unique_id_t riid,
audio_session_t session,
uid_t uid,
const audio_config_base_t *config,