audio policy: improve input device connection logic

Do not systematically close all inputs when an input device is connected
or disconnected but only those affected by the change.

Also:
- refactor setDeviceConnectionStateInt() to align input and output
devices connection sequence
- remove unused "inputs" argument to checkInputsForDevice()

Bug: 126370328
Test: phone call, video call , camcorder, assistant, auto projected
Change-Id: I27734b32da97ad4790d6cd74eaaf866e414db211
gugelfrei
Eric Laurent 5 years ago
parent 8263e3519b
commit 0dd5185555

@ -273,8 +273,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceT
// handle input devices
if (audio_is_input_device(deviceType)) {
SortedVector <audio_io_handle_t> inputs;
ssize_t index = mAvailableInputDevices.indexOf(device);
switch (state)
{
@ -284,11 +282,18 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceT
ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
return INVALID_OPERATION;
}
if (mAvailableInputDevices.add(device) < 0) {
return NO_MEMORY;
}
// Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
// 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) {
mAvailableInputDevices.remove(device);
broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
mHwModules.cleanUpForDevice(device);
@ -296,9 +301,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceT
return INVALID_OPERATION;
}
if (mAvailableInputDevices.add(device) < 0) {
return NO_MEMORY;
}
} break;
// handle input device disconnection
@ -313,8 +315,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceT
// Set Disconnect to HALs
broadcastDeviceConnectionState(device, state);
checkInputsForDevice(device, state, inputs);
mAvailableInputDevices.remove(device);
checkInputsForDevice(device, state);
} break;
default:
@ -325,7 +328,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceT
// Propagate device availability to Engine
setEngineDeviceConnectionState(device, state);
closeAllInputs();
checkCloseInputs();
// As the input device list can impact the output device selection, update
// getDeviceForStrategy() cache
updateDevicesAndOutputs();
@ -2342,9 +2345,39 @@ void AudioPolicyManager::closeClient(audio_port_handle_t portId)
releaseInput(portId);
}
void AudioPolicyManager::closeAllInputs() {
while (mInputs.size() != 0) {
closeInput(mInputs.keyAt(0));
void AudioPolicyManager::checkCloseInputs() {
// After connecting or disconnecting an input device, close input if:
// - it has no client (was just opened to check profile) OR
// - none of its supported devices are connected anymore OR
// - one of its clients cannot be routed to one of its supported
// devices anymore. Otherwise update device selection
std::vector<audio_io_handle_t> inputsToClose;
for (size_t i = 0; i < mInputs.size(); i++) {
const sp<AudioInputDescriptor> input = mInputs.valueAt(i);
if (input->clientsList().size() == 0
|| !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) {
inputsToClose.push_back(mInputs.keyAt(i));
} else {
bool close = false;
for (const auto& client : input->clientsList()) {
sp<DeviceDescriptor> device =
mEngine->getInputDeviceForAttributes(client->attributes());
if (!input->supportedDevices().contains(device)) {
close = true;
break;
}
}
if (close) {
inputsToClose.push_back(mInputs.keyAt(i));
} else {
setInputDevice(input->mIoHandle, getNewInputDevice(input));
}
}
}
for (const audio_io_handle_t handle : inputsToClose) {
ALOGV("%s closing input %d", __func__, handle);
closeInput(handle);
}
}
@ -4684,8 +4717,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
}
status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& device,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& inputs)
audio_policy_dev_state_t state)
{
sp<AudioInputDescriptor> desc;
@ -4695,16 +4727,7 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
}
if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
// first list already open inputs that can be routed to this device
for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
desc = mInputs.valueAt(input_index);
if (desc->mProfile->supportsDeviceTypes(device->type())) {
ALOGV("checkInputsForDevice(): adding opened input %d", mInputs.keyAt(input_index));
inputs.add(mInputs.keyAt(input_index));
}
}
// then look for input profiles that can be routed to this device
// look for input profiles that can be routed to this device
SortedVector< sp<IOProfile> > profiles;
for (const auto& hwModule : mHwModules) {
for (size_t profile_index = 0;
@ -4720,8 +4743,9 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
}
}
if (profiles.isEmpty() && inputs.isEmpty()) {
ALOGW("%s: No input available for device %s", __func__, device->toString().c_str());
if (profiles.isEmpty()) {
ALOGW("%s: No input profile available for device %s",
__func__, device->toString().c_str());
return BAD_VALUE;
}
@ -4774,7 +4798,7 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
input = AUDIO_IO_HANDLE_NONE;
}
if (input != 0) {
if (input != AUDIO_IO_HANDLE_NONE) {
addInput(input, desc);
}
} // endif input != 0
@ -4785,7 +4809,6 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
profiles.removeAt(profile_index);
profile_index--;
} else {
inputs.add(input);
if (audio_device_is_digital(device->type())) {
device->importAudioPort(profile);
}
@ -4799,15 +4822,6 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
}
} else {
// Disconnect
// check if one opened input is not needed any more after disconnecting one device
for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
desc = mInputs.valueAt(input_index);
if (!mAvailableInputDevices.containsAtLeastOne(desc->supportedDevices())) {
ALOGV("checkInputsForDevice(): disconnecting adding input %d",
mInputs.keyAt(input_index));
inputs.add(mInputs.keyAt(input_index));
}
}
// Clear any profiles associated with the disconnected device.
for (const auto& hwModule : mHwModules) {
for (size_t profile_index = 0;

@ -142,7 +142,7 @@ public:
// indicates to the audio policy manager that the input stops being used.
virtual status_t stopInput(audio_port_handle_t portId);
virtual void releaseInput(audio_port_handle_t portId);
virtual void closeAllInputs();
virtual void checkCloseInputs();
/**
* @brief initStreamVolume: even if the engine volume files provides min and max, keep this
* api for compatibility reason.
@ -486,8 +486,7 @@ protected:
SortedVector<audio_io_handle_t>& outputs);
status_t checkInputsForDevice(const sp<DeviceDescriptor>& device,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& inputs);
audio_policy_dev_state_t state);
// close an output and its companion duplicating output.
void closeOutput(audio_io_handle_t output);

Loading…
Cancel
Save