|
|
|
@ -136,27 +136,23 @@ status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced
|
|
|
|
|
return EngineBase::setForceUse(usage, config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
DeviceVector availableOutputDevices,
|
|
|
|
|
DeviceVector availableInputDevices,
|
|
|
|
|
const SwAudioOutputCollection &outputs,
|
|
|
|
|
uint32_t outputDeviceTypesToIgnore) const
|
|
|
|
|
DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
DeviceVector availableOutputDevices,
|
|
|
|
|
DeviceVector availableInputDevices,
|
|
|
|
|
const SwAudioOutputCollection &outputs) const
|
|
|
|
|
{
|
|
|
|
|
uint32_t device = AUDIO_DEVICE_NONE;
|
|
|
|
|
uint32_t availableOutputDevicesType =
|
|
|
|
|
availableOutputDevices.types() & ~outputDeviceTypesToIgnore;
|
|
|
|
|
DeviceVector devices;
|
|
|
|
|
|
|
|
|
|
switch (strategy) {
|
|
|
|
|
|
|
|
|
|
case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case STRATEGY_SONIFICATION_RESPECTFUL:
|
|
|
|
|
if (isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
|
|
|
|
|
device = getDeviceForStrategyInt(
|
|
|
|
|
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
|
|
|
|
|
outputDeviceTypesToIgnore);
|
|
|
|
|
devices = getDevicesForStrategyInt(
|
|
|
|
|
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
|
|
|
|
|
} else {
|
|
|
|
|
bool media_active_locally =
|
|
|
|
|
outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC),
|
|
|
|
@ -165,17 +161,18 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
|
|
|
|
|
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
|
|
|
|
|
// routing is same as media without the "remote" device
|
|
|
|
|
device = getDeviceForStrategyInt(STRATEGY_MEDIA,
|
|
|
|
|
availableOutputDevices.remove(availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_REMOTE_SUBMIX));
|
|
|
|
|
devices = getDevicesForStrategyInt(STRATEGY_MEDIA,
|
|
|
|
|
availableOutputDevices,
|
|
|
|
|
availableInputDevices, outputs,
|
|
|
|
|
AUDIO_DEVICE_OUT_REMOTE_SUBMIX | outputDeviceTypesToIgnore);
|
|
|
|
|
availableInputDevices, outputs);
|
|
|
|
|
// if no media is playing on the device, check for mandatory use of "safe" speaker
|
|
|
|
|
// when media would have played on speaker, and the safe speaker path is available
|
|
|
|
|
if (!media_active_locally
|
|
|
|
|
&& (device & AUDIO_DEVICE_OUT_SPEAKER)
|
|
|
|
|
&& (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
|
|
|
|
|
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
|
|
|
|
|
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
if (!media_active_locally) {
|
|
|
|
|
devices.replaceDevicesByType(
|
|
|
|
|
AUDIO_DEVICE_OUT_SPEAKER,
|
|
|
|
|
availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -183,9 +180,8 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
case STRATEGY_DTMF:
|
|
|
|
|
if (!isInCall()) {
|
|
|
|
|
// when off call, DTMF strategy follows the same rules as MEDIA strategy
|
|
|
|
|
device = getDeviceForStrategyInt(
|
|
|
|
|
STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs,
|
|
|
|
|
outputDeviceTypesToIgnore);
|
|
|
|
|
devices = getDevicesForStrategyInt(
|
|
|
|
|
STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// when in call, DTMF and PHONE strategies follow the same rules
|
|
|
|
@ -197,24 +193,27 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
// - cannot route from voice call RX OR
|
|
|
|
|
// - audio HAL version is < 3.0 and TX device is on the primary HW module
|
|
|
|
|
if (getPhoneState() == AUDIO_MODE_IN_CALL) {
|
|
|
|
|
audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
|
|
|
|
|
audio_devices_t txDevice = getDeviceForInputSource(
|
|
|
|
|
AUDIO_SOURCE_VOICE_COMMUNICATION)->type();
|
|
|
|
|
sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
|
|
|
|
|
audio_devices_t availPrimaryInputDevices =
|
|
|
|
|
availableInputDevices.getDeviceTypesFromHwModule(primaryOutput->getModuleHandle());
|
|
|
|
|
DeviceVector availPrimaryInputDevices =
|
|
|
|
|
availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
|
|
|
|
|
|
|
|
|
|
// TODO: getPrimaryOutput return only devices from first module in
|
|
|
|
|
// audio_policy_configuration.xml, hearing aid is not there, but it's
|
|
|
|
|
// a primary device
|
|
|
|
|
// FIXME: this is not the right way of solving this problem
|
|
|
|
|
audio_devices_t availPrimaryOutputDevices =
|
|
|
|
|
(primaryOutput->supportedDevices().types() | AUDIO_DEVICE_OUT_HEARING_AID) &
|
|
|
|
|
availableOutputDevices.types();
|
|
|
|
|
|
|
|
|
|
if (((availableInputDevices.types() &
|
|
|
|
|
AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
|
|
|
|
|
(((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
|
|
|
|
|
(primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) {
|
|
|
|
|
availableOutputDevicesType = availPrimaryOutputDevices;
|
|
|
|
|
DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
primaryOutput->supportedDevices().types());
|
|
|
|
|
availPrimaryOutputDevices.add(
|
|
|
|
|
availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID));
|
|
|
|
|
|
|
|
|
|
if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
|
|
|
|
|
String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
|
|
|
|
|
((availPrimaryInputDevices.getDevice(
|
|
|
|
|
txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
|
|
|
|
|
(primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) {
|
|
|
|
|
availableOutputDevices = availPrimaryOutputDevices;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// for phone strategy, we first consider the forced use and then the available devices by
|
|
|
|
@ -222,49 +221,40 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
|
|
|
|
|
case AUDIO_POLICY_FORCE_BT_SCO:
|
|
|
|
|
if (!isInCall() || strategy != STRATEGY_DTMF) {
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
|
|
|
|
|
if (device) break;
|
|
|
|
|
devices = availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
|
|
|
|
|
if (!devices.isEmpty()) break;
|
|
|
|
|
}
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
|
|
|
|
|
if (device) break;
|
|
|
|
|
devices = availableOutputDevices.getFirstDevicesFromTypes({
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
|
|
|
|
|
if (!devices.isEmpty()) break;
|
|
|
|
|
// if SCO device is requested but no SCO device is available, fall back to default case
|
|
|
|
|
FALLTHROUGH_INTENDED;
|
|
|
|
|
|
|
|
|
|
default: // FORCE_NONE
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID;
|
|
|
|
|
if (device) break;
|
|
|
|
|
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
|
|
|
|
|
if (!devices.isEmpty()) break;
|
|
|
|
|
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
|
|
|
|
|
if (!isInCall() &&
|
|
|
|
|
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
|
|
|
|
|
outputs.isA2dpSupported()) {
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
|
|
|
|
|
if (device) break;
|
|
|
|
|
devices = availableOutputDevices.getFirstDevicesFromTypes({
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
|
|
|
|
|
if (!devices.isEmpty()) break;
|
|
|
|
|
}
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
|
|
|
|
|
if (device) break;
|
|
|
|
|
devices = availableOutputDevices.getFirstDevicesFromTypes({
|
|
|
|
|
AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_OUT_USB_DEVICE});
|
|
|
|
|
if (!devices.isEmpty()) break;
|
|
|
|
|
if (!isInCall()) {
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
|
|
|
|
|
if (device) break;
|
|
|
|
|
devices = availableOutputDevices.getFirstDevicesFromTypes({
|
|
|
|
|
AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
|
|
|
|
|
if (!devices.isEmpty()) break;
|
|
|
|
|
}
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
|
|
|
|
|
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_EARPIECE);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AUDIO_POLICY_FORCE_SPEAKER:
|
|
|
|
@ -273,22 +263,18 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
if (!isInCall() &&
|
|
|
|
|
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
|
|
|
|
|
outputs.isA2dpSupported()) {
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
|
|
|
|
|
if (device) break;
|
|
|
|
|
devices = availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
|
|
|
|
|
if (!devices.isEmpty()) break;
|
|
|
|
|
}
|
|
|
|
|
if (!isInCall()) {
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
|
|
|
|
|
if (device) break;
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
|
|
|
|
|
if (device) break;
|
|
|
|
|
devices = availableOutputDevices.getFirstDevicesFromTypes({
|
|
|
|
|
AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
|
|
|
|
|
AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_AUX_DIGITAL,
|
|
|
|
|
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
|
|
|
|
|
if (!devices.isEmpty()) break;
|
|
|
|
|
}
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -298,9 +284,8 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
// If incall, just select the STRATEGY_PHONE device
|
|
|
|
|
if (isInCall() ||
|
|
|
|
|
outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
|
|
|
|
|
device = getDeviceForStrategyInt(
|
|
|
|
|
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
|
|
|
|
|
outputDeviceTypesToIgnore);
|
|
|
|
|
devices = getDevicesForStrategyInt(
|
|
|
|
|
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
FALLTHROUGH_INTENDED;
|
|
|
|
@ -313,41 +298,37 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
|
|
|
|
|
if ((strategy == STRATEGY_SONIFICATION) ||
|
|
|
|
|
(getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
|
|
|
|
|
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if SCO headset is connected and we are told to use it, play ringtone over
|
|
|
|
|
// speaker and BT SCO
|
|
|
|
|
if ((availableOutputDevicesType & AUDIO_DEVICE_OUT_ALL_SCO) != 0) {
|
|
|
|
|
uint32_t device2 = AUDIO_DEVICE_NONE;
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
|
|
|
|
|
}
|
|
|
|
|
if (!availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_ALL_SCO).isEmpty()) {
|
|
|
|
|
DeviceVector devices2;
|
|
|
|
|
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
|
|
|
|
|
// Use ONLY Bluetooth SCO output when ringing in vibration mode
|
|
|
|
|
if (!((getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
|
|
|
|
|
&& (strategy == STRATEGY_ENFORCED_AUDIBLE))) {
|
|
|
|
|
if (getForceUse(AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING)
|
|
|
|
|
== AUDIO_POLICY_FORCE_BT_SCO) {
|
|
|
|
|
if (device2 != AUDIO_DEVICE_NONE) {
|
|
|
|
|
device = device2;
|
|
|
|
|
if (!devices2.isEmpty()) {
|
|
|
|
|
devices = devices2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Use both Bluetooth SCO and phone default output when ringing in normal mode
|
|
|
|
|
if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) {
|
|
|
|
|
if ((strategy == STRATEGY_SONIFICATION) &&
|
|
|
|
|
(device & AUDIO_DEVICE_OUT_SPEAKER) &&
|
|
|
|
|
(availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
|
|
|
|
|
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
|
|
|
|
|
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
if (strategy == STRATEGY_SONIFICATION) {
|
|
|
|
|
devices.replaceDevicesByType(
|
|
|
|
|
AUDIO_DEVICE_OUT_SPEAKER,
|
|
|
|
|
availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
|
|
|
|
|
}
|
|
|
|
|
if (device2 != AUDIO_DEVICE_NONE) {
|
|
|
|
|
device |= device2;
|
|
|
|
|
if (!devices2.isEmpty()) {
|
|
|
|
|
devices.add(devices2);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -361,25 +342,20 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
// compressed format as they would likely not be mixed and dropped.
|
|
|
|
|
for (size_t i = 0; i < outputs.size(); i++) {
|
|
|
|
|
sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
|
|
|
|
|
audio_devices_t devices = desc->devices().types() &
|
|
|
|
|
(AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
|
|
|
|
|
if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
|
|
|
|
|
devices != AUDIO_DEVICE_NONE) {
|
|
|
|
|
availableOutputDevicesType = availableOutputDevices.types() & ~devices;
|
|
|
|
|
if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) {
|
|
|
|
|
availableOutputDevices.remove(desc->devices().getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF
|
|
|
|
|
| AUDIO_DEVICE_OUT_HDMI_ARC));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
availableOutputDevices =
|
|
|
|
|
availableOutputDevices.getDevicesFromTypeMask(availableOutputDevicesType);
|
|
|
|
|
if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
|
|
|
|
|
outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) {
|
|
|
|
|
return getDeviceForStrategyInt(
|
|
|
|
|
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
|
|
|
|
|
outputDeviceTypesToIgnore);
|
|
|
|
|
return getDevicesForStrategyInt(
|
|
|
|
|
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
|
|
|
|
|
}
|
|
|
|
|
if (isInCall()) {
|
|
|
|
|
return getDeviceForStrategyInt(
|
|
|
|
|
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
|
|
|
|
|
outputDeviceTypesToIgnore);
|
|
|
|
|
return getDevicesForStrategyInt(
|
|
|
|
|
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA
|
|
|
|
@ -388,128 +364,116 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
|
|
|
|
|
// FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
|
|
|
|
|
case STRATEGY_REROUTING:
|
|
|
|
|
case STRATEGY_MEDIA: {
|
|
|
|
|
uint32_t device2 = AUDIO_DEVICE_NONE;
|
|
|
|
|
DeviceVector devices2;
|
|
|
|
|
if (strategy != STRATEGY_SONIFICATION) {
|
|
|
|
|
// no sonification on remote submix (e.g. WFD)
|
|
|
|
|
if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
|
|
|
|
|
String8("0"), AUDIO_FORMAT_DEFAULT) != 0) {
|
|
|
|
|
device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
|
|
|
|
|
sp<DeviceDescriptor> remoteSubmix;
|
|
|
|
|
if ((remoteSubmix = availableOutputDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0"),
|
|
|
|
|
AUDIO_FORMAT_DEFAULT)) != nullptr) {
|
|
|
|
|
devices2.add(remoteSubmix);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (isInCall() && (strategy == STRATEGY_MEDIA)) {
|
|
|
|
|
device = getDeviceForStrategyInt(
|
|
|
|
|
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
|
|
|
|
|
outputDeviceTypesToIgnore);
|
|
|
|
|
devices = getDevicesForStrategyInt(
|
|
|
|
|
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261).
|
|
|
|
|
if ((device2 == AUDIO_DEVICE_NONE) &&
|
|
|
|
|
if ((devices2.isEmpty()) &&
|
|
|
|
|
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID;
|
|
|
|
|
devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
|
|
|
|
|
}
|
|
|
|
|
if ((device2 == AUDIO_DEVICE_NONE) &&
|
|
|
|
|
if ((devices2.isEmpty()) &&
|
|
|
|
|
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
|
|
|
|
|
outputs.isA2dpSupported()) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
|
|
|
|
|
}
|
|
|
|
|
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
|
|
|
|
|
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER});
|
|
|
|
|
}
|
|
|
|
|
if ((device2 == AUDIO_DEVICE_NONE) &&
|
|
|
|
|
if ((devices2.isEmpty()) &&
|
|
|
|
|
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
|
|
|
|
|
devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
|
|
|
|
|
if (devices2.isEmpty()) {
|
|
|
|
|
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
|
|
|
|
|
AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_LINE,
|
|
|
|
|
AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
|
|
|
|
|
AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET});
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
|
|
|
|
|
}
|
|
|
|
|
if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
|
|
|
|
|
if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
|
|
|
|
|
// no sonification on aux digital (e.g. HDMI)
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
|
|
|
|
|
devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_AUX_DIGITAL);
|
|
|
|
|
}
|
|
|
|
|
if ((device2 == AUDIO_DEVICE_NONE) &&
|
|
|
|
|
if ((devices2.isEmpty()) &&
|
|
|
|
|
(getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
|
|
|
|
|
devices2 = availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
|
|
|
|
|
}
|
|
|
|
|
if (device2 == AUDIO_DEVICE_NONE) {
|
|
|
|
|
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
if (devices2.isEmpty()) {
|
|
|
|
|
devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
|
|
|
|
|
}
|
|
|
|
|
int device3 = AUDIO_DEVICE_NONE;
|
|
|
|
|
DeviceVector devices3;
|
|
|
|
|
if (strategy == STRATEGY_MEDIA) {
|
|
|
|
|
// ARC, SPDIF and AUX_LINE can co-exist with others.
|
|
|
|
|
device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
|
|
|
|
|
device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
|
|
|
|
|
device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
|
|
|
|
|
devices3 = availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_HDMI_ARC | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_AUX_LINE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
device2 |= device3;
|
|
|
|
|
devices2.add(devices3);
|
|
|
|
|
// device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
|
|
|
|
|
// STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
|
|
|
|
|
device |= device2;
|
|
|
|
|
devices.add(devices2);
|
|
|
|
|
|
|
|
|
|
// If hdmi system audio mode is on, remove speaker out of output list.
|
|
|
|
|
if ((strategy == STRATEGY_MEDIA) &&
|
|
|
|
|
(getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) ==
|
|
|
|
|
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
|
|
|
|
|
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
devices.remove(devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// for STRATEGY_SONIFICATION:
|
|
|
|
|
// if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
|
|
|
|
|
if ((strategy == STRATEGY_SONIFICATION) &&
|
|
|
|
|
(device & AUDIO_DEVICE_OUT_SPEAKER) &&
|
|
|
|
|
(availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
|
|
|
|
|
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
|
|
|
|
|
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
|
|
|
|
|
if (strategy == STRATEGY_SONIFICATION) {
|
|
|
|
|
devices.replaceDevicesByType(
|
|
|
|
|
AUDIO_DEVICE_OUT_SPEAKER,
|
|
|
|
|
availableOutputDevices.getDevicesFromTypeMask(
|
|
|
|
|
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
|
|
|
|
|
}
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
|
|
|
|
|
ALOGW("getDevicesForStrategy() unknown strategy: %d", strategy);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (device == AUDIO_DEVICE_NONE) {
|
|
|
|
|
ALOGV("getDeviceForStrategy() no device found for strategy %d", strategy);
|
|
|
|
|
device = getApmObserver()->getDefaultOutputDevice()->type();
|
|
|
|
|
ALOGE_IF(device == AUDIO_DEVICE_NONE,
|
|
|
|
|
"getDeviceForStrategy() no default device defined");
|
|
|
|
|
if (devices.isEmpty()) {
|
|
|
|
|
ALOGV("getDevicesForStrategy() no device found for strategy %d", strategy);
|
|
|
|
|
sp<DeviceDescriptor> defaultOutputDevice = getApmObserver()->getDefaultOutputDevice();
|
|
|
|
|
if (defaultOutputDevice != nullptr) {
|
|
|
|
|
devices.add(defaultOutputDevice);
|
|
|
|
|
}
|
|
|
|
|
ALOGE_IF(devices.isEmpty(),
|
|
|
|
|
"getDevicesForStrategy() no default device defined");
|
|
|
|
|
}
|
|
|
|
|
ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
|
|
|
|
|
return device;
|
|
|
|
|
|
|
|
|
|
ALOGVV("getDevices"
|
|
|
|
|
"ForStrategy() strategy %d, device %x", strategy, devices.types());
|
|
|
|
|
return devices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const
|
|
|
|
|
sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource) const
|
|
|
|
|
{
|
|
|
|
|
const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
|
|
|
|
|
const DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
|
|
|
|
|
const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
|
|
|
|
|
audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
|
|
|
|
|
DeviceVector availableDevices = availableInputDevices;
|
|
|
|
|
sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
|
|
|
|
|
audio_devices_t availablePrimaryDeviceTypes = availableInputDevices.getDeviceTypesFromHwModule(
|
|
|
|
|
primaryOutput->getModuleHandle()) & ~AUDIO_DEVICE_BIT_IN;
|
|
|
|
|
uint32_t device = AUDIO_DEVICE_NONE;
|
|
|
|
|
DeviceVector availablePrimaryDevices = availableInputDevices.getDevicesFromHwModule(
|
|
|
|
|
primaryOutput->getModuleHandle());
|
|
|
|
|
sp<DeviceDescriptor> device;
|
|
|
|
|
|
|
|
|
|
// when a call is active, force device selection to match source VOICE_COMMUNICATION
|
|
|
|
|
// for most other input sources to avoid rerouting call TX audio
|
|
|
|
@ -532,57 +496,47 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons
|
|
|
|
|
switch (inputSource) {
|
|
|
|
|
case AUDIO_SOURCE_DEFAULT:
|
|
|
|
|
case AUDIO_SOURCE_MIC:
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
|
|
|
|
|
} else if ((getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) &&
|
|
|
|
|
(availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_DEVICE;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
if (device != nullptr) break;
|
|
|
|
|
if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
if (device != nullptr) break;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getFirstExistingDevice({
|
|
|
|
|
AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AUDIO_SOURCE_VOICE_COMMUNICATION:
|
|
|
|
|
// Allow only use of devices on primary input if in call and HAL does not support routing
|
|
|
|
|
// to voice call path.
|
|
|
|
|
if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
|
|
|
|
|
(availableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) {
|
|
|
|
|
availableDeviceTypes = availablePrimaryDeviceTypes;
|
|
|
|
|
(availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX,
|
|
|
|
|
String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) {
|
|
|
|
|
availableDevices = availablePrimaryDevices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
|
|
|
|
|
case AUDIO_POLICY_FORCE_BT_SCO:
|
|
|
|
|
// if SCO device is requested but no SCO device is available, fall back to default case
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
if (device != nullptr) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
FALLTHROUGH_INTENDED;
|
|
|
|
|
|
|
|
|
|
default: // FORCE_NONE
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_DEVICE;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getFirstExistingDevice({
|
|
|
|
|
AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AUDIO_POLICY_FORCE_SPEAKER:
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BACK_MIC;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getFirstExistingDevice({
|
|
|
|
|
AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -591,77 +545,60 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons
|
|
|
|
|
case AUDIO_SOURCE_UNPROCESSED:
|
|
|
|
|
case AUDIO_SOURCE_HOTWORD:
|
|
|
|
|
if (inputSource == AUDIO_SOURCE_HOTWORD) {
|
|
|
|
|
availableDeviceTypes = availablePrimaryDeviceTypes;
|
|
|
|
|
}
|
|
|
|
|
if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO &&
|
|
|
|
|
availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_DEVICE;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
|
|
|
|
|
availableDevices = availablePrimaryDevices;
|
|
|
|
|
}
|
|
|
|
|
if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
if (device != nullptr) break;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getFirstExistingDevice({
|
|
|
|
|
AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
|
|
|
|
|
break;
|
|
|
|
|
case AUDIO_SOURCE_CAMCORDER:
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BACK_MIC;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
|
|
|
|
|
// This is specifically for a device without built-in mic
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_DEVICE;
|
|
|
|
|
}
|
|
|
|
|
// For a device without built-in mic, adding usb device
|
|
|
|
|
device = availableDevices.getFirstExistingDevice({
|
|
|
|
|
AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
|
|
|
|
|
AUDIO_DEVICE_IN_USB_DEVICE});
|
|
|
|
|
break;
|
|
|
|
|
case AUDIO_SOURCE_VOICE_DOWNLINK:
|
|
|
|
|
case AUDIO_SOURCE_VOICE_CALL:
|
|
|
|
|
case AUDIO_SOURCE_VOICE_UPLINK:
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_VOICE_CALL;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_VOICE_CALL, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
break;
|
|
|
|
|
case AUDIO_SOURCE_VOICE_PERFORMANCE:
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_HEADSET;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_USB_DEVICE;
|
|
|
|
|
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getFirstExistingDevice({
|
|
|
|
|
AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
|
|
|
|
|
AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
|
|
|
|
|
break;
|
|
|
|
|
case AUDIO_SOURCE_REMOTE_SUBMIX:
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
break;
|
|
|
|
|
case AUDIO_SOURCE_FM_TUNER:
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_FM_TUNER;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_FM_TUNER, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
break;
|
|
|
|
|
case AUDIO_SOURCE_ECHO_REFERENCE:
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_ECHO_REFERENCE) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_ECHO_REFERENCE;
|
|
|
|
|
}
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_ECHO_REFERENCE, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (device == AUDIO_DEVICE_NONE) {
|
|
|
|
|
if (device == nullptr) {
|
|
|
|
|
ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
|
|
|
|
|
if (availableDeviceTypes & AUDIO_DEVICE_IN_STUB) {
|
|
|
|
|
device = AUDIO_DEVICE_IN_STUB;
|
|
|
|
|
}
|
|
|
|
|
ALOGE_IF(device == AUDIO_DEVICE_NONE,
|
|
|
|
|
device = availableDevices.getDevice(
|
|
|
|
|
AUDIO_DEVICE_IN_STUB, String8(""), AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
ALOGE_IF(device == nullptr,
|
|
|
|
|
"getDeviceForInputSource() no default device defined");
|
|
|
|
|
}
|
|
|
|
|
ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
|
|
|
|
|
ALOGV_IF(device != nullptr,
|
|
|
|
|
"getDeviceForInputSource()input source %d, device %08x",
|
|
|
|
|
inputSource, device->type());
|
|
|
|
|
return device;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -684,11 +621,9 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) c
|
|
|
|
|
|
|
|
|
|
auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
|
|
|
|
|
mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
|
|
|
|
|
audio_devices_t devices = getDeviceForStrategyInt(legacyStrategy,
|
|
|
|
|
availableOutputDevices,
|
|
|
|
|
availableInputDevices, outputs,
|
|
|
|
|
(uint32_t)AUDIO_DEVICE_NONE);
|
|
|
|
|
return availableOutputDevices.getDevicesFromTypeMask(devices);
|
|
|
|
|
return getDevicesForStrategyInt(legacyStrategy,
|
|
|
|
|
availableOutputDevices,
|
|
|
|
|
availableInputDevices, outputs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
|
|
|
|
@ -747,17 +682,21 @@ sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_
|
|
|
|
|
if (device != nullptr) {
|
|
|
|
|
return device;
|
|
|
|
|
}
|
|
|
|
|
audio_devices_t deviceType = getDeviceForInputSource(attr.source);
|
|
|
|
|
|
|
|
|
|
if (audio_is_remote_submix_device(deviceType)) {
|
|
|
|
|
address = "0";
|
|
|
|
|
std::size_t pos;
|
|
|
|
|
std::string tags { attr.tags };
|
|
|
|
|
if ((pos = tags.find("addr=")) != std::string::npos) {
|
|
|
|
|
address = tags.substr(pos + std::strlen("addr="));
|
|
|
|
|
}
|
|
|
|
|
device = getDeviceForInputSource(attr.source);
|
|
|
|
|
if (device == nullptr || !audio_is_remote_submix_device(device->type())) {
|
|
|
|
|
// Return immediately if the device is null or it is not a remote submix device.
|
|
|
|
|
return device;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For remote submix device, try to find the device by address.
|
|
|
|
|
address = "0";
|
|
|
|
|
std::size_t pos;
|
|
|
|
|
std::string tags { attr.tags };
|
|
|
|
|
if ((pos = tags.find("addr=")) != std::string::npos) {
|
|
|
|
|
address = tags.substr(pos + std::strlen("addr="));
|
|
|
|
|
}
|
|
|
|
|
return availableInputDevices.getDevice(deviceType,
|
|
|
|
|
return availableInputDevices.getDevice(device->type(),
|
|
|
|
|
String8(address.c_str()),
|
|
|
|
|
AUDIO_FORMAT_DEFAULT);
|
|
|
|
|
}
|
|
|
|
|