audio policy: protect against null input device selection
Made two improvements in audio policy engine to avoid problems when
no suitable input device can be found for a given use case:
1) make sure getDeviceForInputSource() returns a valid device for
VOICE_COMMUNICATION use case.
2) in the general case, do not crash if getDeviceForInputSource()
returns a null device.
Bug: 274001478
Test: make
Change-Id: Ib7ad122b32f54cc429f0b4ab3ff58d4ff04ea09b
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index a6821c7..c7e2103 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -166,8 +166,12 @@
// - 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)->type();
+ audio_devices_t txDevice = AUDIO_DEVICE_NONE;
+ sp<DeviceDescriptor> txDeviceDesc =
+ getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+ if (txDeviceDesc != nullptr) {
+ txDevice = txDeviceDesc->type();
+ }
sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
LOG_ALWAYS_FATAL_IF(primaryOutput == nullptr, "Primary output not found");
DeviceVector availPrimaryInputDevices =
@@ -594,22 +598,26 @@
}
}
switch (commDeviceType) {
- case AUDIO_DEVICE_OUT_BLE_HEADSET:
- device = availableDevices.getDevice(
- AUDIO_DEVICE_IN_BLE_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
- break;
case AUDIO_DEVICE_OUT_SPEAKER:
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_USB_HEADSET});
break;
+ case AUDIO_DEVICE_OUT_BLE_HEADSET:
+ device = availableDevices.getDevice(
+ AUDIO_DEVICE_IN_BLE_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+ if (device != nullptr) {
+ break;
+ }
+ ALOGE("%s LE Audio selected for communication but input device not available",
+ __func__);
+ FALLTHROUGH_INTENDED;
default: // FORCE_NONE
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
AUDIO_DEVICE_IN_BUILTIN_MIC});
break;
-
}
break;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 22e4686..f5c7a71 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -671,7 +671,10 @@
audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr);
- ALOG_ASSERT(txSourceDevice != 0, "%s() input selected device not available", __func__);
+ if (txSourceDevice == nullptr) {
+ ALOGE("%s() selected input device not available", __func__);
+ return INVALID_OPERATION;
+ }
ALOGV("%s device rxDevice %s txDevice %s", __func__,
rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());
@@ -5327,7 +5330,11 @@
*session = (audio_session_t)mpClientInterface->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
*ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_INPUT);
audio_attributes_t attr = { .source = AUDIO_SOURCE_HOTWORD };
- *device = mEngine->getInputDeviceForAttributes(attr)->type();
+ sp<DeviceDescriptor> deviceDesc = mEngine->getInputDeviceForAttributes(attr);
+ if (deviceDesc == nullptr) {
+ return INVALID_OPERATION;
+ }
+ *device = deviceDesc->type();
return mSoundTriggerSessions.acquireSession(*session, *ioHandle);
}