audiopolicy: Add support for hybrid mode on A2DP
Add support in AudioPolicyManager to select a module,
device or output based on device type and codec.
Implement hybrid mode with A2DP which enables runtime
switching between HALs for A2DP based on offload support
for specific A2DP codecs.
Optimize A2DP active device change and device config
change in AudioPolicyManager.
Bug: 111812273
Test: make
Change-Id: I246d71dd08bacbca6ed9b0012e7d7698bd8a0953
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index baeae8b..0beb65d 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -784,7 +784,8 @@
status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
const char *address = "";
@@ -798,7 +799,7 @@
if (device_name != NULL) {
name = device_name;
}
- return aps->setDeviceConnectionState(device, state, address, name);
+ return aps->setDeviceConnectionState(device, state, address, name, encodedFormat);
}
audio_policy_dev_state_t AudioSystem::getDeviceConnectionState(audio_devices_t device,
@@ -812,7 +813,8 @@
status_t AudioSystem::handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
const char *address = "";
@@ -826,7 +828,7 @@
if (device_name != NULL) {
name = device_name;
}
- return aps->handleDeviceConfigChange(device, address, name);
+ return aps->handleDeviceConfigChange(device, address, name, encodedFormat);
}
status_t AudioSystem::setPhoneState(audio_mode_t state)
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 272415c..0fae2a1 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -108,7 +108,8 @@
audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -116,6 +117,7 @@
data.writeInt32(static_cast <uint32_t>(state));
data.writeCString(device_address);
data.writeCString(device_name);
+ data.writeInt32(static_cast <uint32_t>(encodedFormat));
remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
@@ -134,13 +136,15 @@
virtual status_t handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(static_cast <uint32_t>(device));
data.writeCString(device_address);
data.writeCString(device_name);
+ data.writeInt32(static_cast <uint32_t>(encodedFormat));
remote()->transact(HANDLE_DEVICE_CONFIG_CHANGE, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
@@ -1121,6 +1125,7 @@
static_cast <audio_policy_dev_state_t>(data.readInt32());
const char *device_address = data.readCString();
const char *device_name = data.readCString();
+ audio_format_t codecFormat = static_cast <audio_format_t>(data.readInt32());
if (device_address == nullptr || device_name == nullptr) {
ALOGE("Bad Binder transaction: SET_DEVICE_CONNECTION_STATE for device %u", device);
reply->writeInt32(static_cast<int32_t> (BAD_VALUE));
@@ -1128,7 +1133,8 @@
reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
state,
device_address,
- device_name)));
+ device_name,
+ codecFormat)));
}
return NO_ERROR;
} break;
@@ -1154,13 +1160,16 @@
static_cast <audio_devices_t>(data.readInt32());
const char *device_address = data.readCString();
const char *device_name = data.readCString();
+ audio_format_t codecFormat =
+ static_cast <audio_format_t>(data.readInt32());
if (device_address == nullptr || device_name == nullptr) {
ALOGE("Bad Binder transaction: HANDLE_DEVICE_CONFIG_CHANGE for device %u", device);
reply->writeInt32(static_cast<int32_t> (BAD_VALUE));
} else {
reply->writeInt32(static_cast<uint32_t> (handleDeviceConfigChange(device,
device_address,
- device_name)));
+ device_name,
+ codecFormat)));
}
return NO_ERROR;
} break;
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 781e9df..2b4a373 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -209,12 +209,14 @@
// IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
//
static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state,
- const char *device_address, const char *device_name);
+ const char *device_address, const char *device_name,
+ audio_format_t encodedFormat);
static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address);
static status_t handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name);
+ const char *device_name,
+ audio_format_t encodedFormat);
static status_t setPhoneState(audio_mode_t state);
static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index fb4fe93..75de8e9 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -44,12 +44,14 @@
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name) = 0;
+ const char *device_name,
+ audio_format_t encodedFormat) = 0;
virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address) = 0;
virtual status_t handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name) = 0;
+ const char *device_name,
+ audio_format_t encodedFormat) = 0;
virtual status_t setPhoneState(audio_mode_t state) = 0;
virtual status_t setForceUse(audio_policy_force_use_t usage,
audio_policy_forced_cfg_t config) = 0;
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 1c2b9d7..8bfb736 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -75,14 +75,16 @@
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name) = 0;
+ const char *device_name,
+ audio_format_t encodedFormat) = 0;
// retrieve a device connection status
virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address) = 0;
// indicate a change in device configuration
virtual status_t handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name) = 0;
+ const char *device_name,
+ audio_format_t encodedFormat) = 0;
// indicate a change in phone state. Valid phones states are defined by audio_mode_t
virtual void setPhoneState(audio_mode_t state) = 0;
// force using a specific device category for the specified usage
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 46a2a40..837ca47 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -76,6 +76,21 @@
}
/**
+ * Check whether audio device has encoding capability.
+ *
+ * @param[in] device to consider
+ *
+ * @return true if device has encoding capability, false otherwise..
+ */
+static inline bool device_has_encoding_capability(audio_devices_t device)
+{
+ if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ return true;
+ }
+ return false;
+}
+
+/**
* Returns the priority of a given audio source for capture. The priority is used when more than one
* capture session is active on a given input stream to determine which session drives routing and
* effect configuration.
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 14b995b..e1ecc61 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -154,6 +154,7 @@
void setDevices(const DeviceVector &devices) { mDevices = devices; }
bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc);
virtual DeviceVector supportedDevices() const;
+ virtual bool deviceSupportsEncodedFormats(audio_devices_t device);
virtual uint32_t latency();
virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
virtual bool isFixedVolume(audio_devices_t device);
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index b581665..cc43fe6 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -44,8 +44,18 @@
const FormatVector& encodedFormats() const { return mEncodedFormats; }
+ audio_format_t getEncodedFormat() { return mCurrentEncodedFormat; }
+
+ void setEncodedFormat(audio_format_t format) {
+ mCurrentEncodedFormat = format;
+ }
+
bool equals(const sp<DeviceDescriptor>& other) const;
+ bool hasCurrentEncodedFormat() const;
+
+ bool supportsFormat(audio_format_t format);
+
// AudioPortConfig
virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
@@ -69,6 +79,7 @@
audio_devices_t mDeviceType;
FormatVector mEncodedFormats;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
+ audio_format_t mCurrentEncodedFormat;
};
class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
@@ -88,9 +99,10 @@
audio_devices_t types() const { return mDeviceTypes; }
- // If 'address' is empty, a device with a non-empty address may be returned
- // if there is no device with the specified 'type' and empty address.
- sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address = {}) const;
+ // If 'address' is empty and 'codec' is AUDIO_FORMAT_DEFAULT, a device with a non-empty
+ // address may be returned if there is no device with the specified 'type' and empty address.
+ sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address,
+ audio_format_t codec) const;
DeviceVector getDevicesFromTypeMask(audio_devices_t types) const;
/**
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index d7dc4b0..eb34da4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -130,9 +130,11 @@
public:
sp<HwModule> getModuleFromName(const char *name) const;
- sp<HwModule> getModuleForDeviceTypes(audio_devices_t device) const;
+ sp<HwModule> getModuleForDeviceTypes(audio_devices_t device,
+ audio_format_t encodedFormat) const;
- sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device) const;
+ sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device,
+ audio_format_t encodedFormat) const;
DeviceVector getAvailableDevicesFromModuleName(const char *name,
const DeviceVector &availableDevices) const;
@@ -149,6 +151,7 @@
* @param type of the device requested
* @param address of the device requested
* @param name of the device that requested
+ * @param encodedFormat if not AUDIO_FORMAT_DEFAULT, must match one supported format
* @param matchAddress true if a strong match is required
* @param allowToCreate true if allowed to create dynamic device (e.g. hdmi, usb...)
* @return device descriptor associated to the type (and address if matchAddress is true)
@@ -156,6 +159,7 @@
sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t type,
const char *address,
const char *name,
+ audio_format_t encodedFormat,
bool allowToCreate = false,
bool matchAddress = true) const;
@@ -171,7 +175,8 @@
*/
sp<DeviceDescriptor> createDevice(const audio_devices_t type,
const char *address,
- const char *name) const;
+ const char *name,
+ const audio_format_t encodedFormat) const;
/**
* @brief cleanUpForDevice: loop on all profiles of all modules to remove device from
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index d0c05a5..dc409a7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -94,7 +94,10 @@
bool supportsDeviceTypes(audio_devices_t device) const
{
if (audio_is_output_devices(device)) {
- return mSupportedDevices.types() & device;
+ if (deviceSupportsEncodedFormats(device)) {
+ return mSupportedDevices.types() & device;
+ }
+ return false;
}
return mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN);
}
@@ -116,6 +119,16 @@
return mSupportedDevices.contains(device);
}
+ bool deviceSupportsEncodedFormats(audio_devices_t device) const
+ {
+ DeviceVector deviceList =
+ mSupportedDevices.getDevicesFromTypeMask(device);
+ if (!deviceList.empty()) {
+ return deviceList.itemAt(0)->hasCurrentEncodedFormat();
+ }
+ return false;
+ }
+
void clearSupportedDevices() { mSupportedDevices.clear(); }
void addSupportedDevice(const sp<DeviceDescriptor> &device)
{
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 643cbd1..57328f0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -364,6 +364,16 @@
return filteredDevices.filter(devices);
}
+bool SwAudioOutputDescriptor::deviceSupportsEncodedFormats(audio_devices_t device)
+{
+ if (isDuplicated()) {
+ return (mOutput1->deviceSupportsEncodedFormats(device)
+ || mOutput2->deviceSupportsEncodedFormats(device));
+ } else {
+ return mProfile->deviceSupportsEncodedFormats(device);
+ }
+}
+
uint32_t SwAudioOutputDescriptor::latency()
{
if (isDuplicated()) {
@@ -687,7 +697,9 @@
for (size_t i = 0; i < size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
if (!outputDesc->isDuplicated() &&
- outputDesc->devices().types() & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ outputDesc->devices().types() & AUDIO_DEVICE_OUT_ALL_A2DP &&
+ outputDesc->deviceSupportsEncodedFormats(
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
return this->keyAt(i);
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index d18091c..799950c 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -296,7 +296,8 @@
// assuming PolicyMix only for remote submix for input
// so mix->mDeviceType can only be AUDIO_DEVICE_OUT_REMOTE_SUBMIX
audio_devices_t device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
- auto mixDevice = availDevices.getDevice(device, mix->mDeviceAddress);
+ auto mixDevice =
+ availDevices.getDevice(device, mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT);
if (mixDevice != nullptr) {
if (policyMix != NULL) {
*policyMix = mix;
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 01111c5..2ed8455 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <audio_utils/string.h>
+#include <set>
#include "DeviceDescriptor.h"
#include "TypeConverter.h"
#include "AudioGain.h"
@@ -37,6 +38,7 @@
AUDIO_PORT_ROLE_SOURCE),
mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
{
+ mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
mAddress = String8("0");
}
@@ -45,6 +47,12 @@
mEncodedFormats.add(AUDIO_FORMAT_AC3);
mEncodedFormats.add(AUDIO_FORMAT_IEC61937);
}
+ // For backward compatibility always indicate support for SBC and AAC if no
+ // supported format is listed in the configuration file
+ if ((type & AUDIO_DEVICE_OUT_ALL_A2DP) != 0 && mEncodedFormats.isEmpty()) {
+ mEncodedFormats.add(AUDIO_FORMAT_SBC);
+ mEncodedFormats.add(AUDIO_FORMAT_AAC);
+ }
}
audio_port_handle_t DeviceDescriptor::getId() const
@@ -58,21 +66,49 @@
mId = getNextUniqueId();
}
-void DeviceDescriptor::detach()
-{
+void DeviceDescriptor::detach() {
mId = AUDIO_PORT_HANDLE_NONE;
AudioPort::detach();
}
+template<typename T>
+bool checkEqual(const T& f1, const T& f2)
+{
+ std::set<typename T::value_type> s1(f1.begin(), f1.end());
+ std::set<typename T::value_type> s2(f2.begin(), f2.end());
+ return s1 == s2;
+}
+
bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
{
// Devices are considered equal if they:
// - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
// - have the same address
+ // - have the same encodingFormats (if device supports encoding)
if (other == 0) {
return false;
}
- return (mDeviceType == other->mDeviceType) && (mAddress == other->mAddress);
+
+ return (mDeviceType == other->mDeviceType) && (mAddress == other->mAddress) &&
+ checkEqual(mEncodedFormats, other->mEncodedFormats);
+}
+
+bool DeviceDescriptor::hasCurrentEncodedFormat() const
+{
+ if (!device_has_encoding_capability(type())) {
+ return true;
+ }
+ return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT);
+}
+
+bool DeviceDescriptor::supportsFormat(audio_format_t format)
+{
+ for (const auto& devFormat : mEncodedFormats) {
+ if (devFormat == format) {
+ return true;
+ }
+ }
+ return false;
}
void DeviceVector::refreshTypes()
@@ -167,12 +203,17 @@
return deviceTypes;
}
-sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address) const
+sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address,
+ audio_format_t format) const
{
sp<DeviceDescriptor> device;
for (size_t i = 0; i < size(); i++) {
if (itemAt(i)->type() == type) {
- if (address == "" || itemAt(i)->address() == address) {
+ // Assign device if address is empty or matches and
+ // format is default or matches
+ if (((address == "" || itemAt(i)->address() == address) &&
+ format == AUDIO_FORMAT_DEFAULT) ||
+ itemAt(i)->supportsFormat(format)) {
device = itemAt(i);
if (itemAt(i)->address() == address) {
break;
@@ -180,8 +221,8 @@
}
}
}
- ALOGV("DeviceVector::%s() for type %08x address \"%s\" found %p",
- __func__, type, address.string(), device.get());
+ ALOGV("DeviceVector::%s() for type %08x address \"%s\" found %p format %08x",
+ __func__, type, address.string(), device.get(), format);
return device;
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 7d2d094..85d9bce 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -273,32 +273,34 @@
return nullptr;
}
-sp <HwModule> HwModuleCollection::getModuleForDeviceTypes(audio_devices_t device) const
+sp <HwModule> HwModuleCollection::getModuleForDeviceTypes(audio_devices_t type,
+ audio_format_t encodedFormat) const
{
for (const auto& module : *this) {
- const auto& profiles = audio_is_output_device(device) ?
+ const auto& profiles = audio_is_output_device(type) ?
module->getOutputProfiles() : module->getInputProfiles();
for (const auto& profile : profiles) {
- if (profile->supportsDeviceTypes(device)) {
- return module;
+ if (profile->supportsDeviceTypes(type)) {
+ if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
+ DeviceVector declaredDevices = module->getDeclaredDevices();
+ sp <DeviceDescriptor> deviceDesc =
+ declaredDevices.getDevice(type, String8(), encodedFormat);
+ if (deviceDesc) {
+ return module;
+ }
+ } else {
+ return module;
+ }
}
}
}
return nullptr;
}
-sp <HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device) const
+sp<HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device,
+ audio_format_t encodedFormat) const
{
- for (const auto& module : *this) {
- const auto& profiles = audio_is_output_device(device->type()) ?
- module->getOutputProfiles() : module->getInputProfiles();
- for (const auto& profile : profiles) {
- if (profile->supportsDevice(device)) {
- return module;
- }
- }
- }
- return nullptr;
+ return getModuleForDeviceTypes(device->type(), encodedFormat);
}
DeviceVector HwModuleCollection::getAvailableDevicesFromModuleName(
@@ -314,6 +316,7 @@
sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t deviceType,
const char *address,
const char *name,
+ const audio_format_t encodedFormat,
bool allowToCreate,
bool matchAddress) const
{
@@ -325,8 +328,14 @@
for (const auto& hwModule : *this) {
DeviceVector moduleDevices = hwModule->getAllDevices();
- auto moduleDevice = moduleDevices.getDevice(deviceType, devAddress);
+ auto moduleDevice = moduleDevices.getDevice(deviceType, devAddress, encodedFormat);
if (moduleDevice) {
+ if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
+ moduleDevice->setEncodedFormat(encodedFormat);
+ if (moduleDevice->address() != devAddress) {
+ moduleDevice->setAddress(devAddress);
+ }
+ }
if (allowToCreate) {
moduleDevice->attach(hwModule);
}
@@ -338,14 +347,15 @@
name, deviceType, address);
return nullptr;
}
- return createDevice(deviceType, address, name);
+ return createDevice(deviceType, address, name, encodedFormat);
}
sp<DeviceDescriptor> HwModuleCollection::createDevice(const audio_devices_t type,
const char *address,
- const char *name) const
+ const char *name,
+ const audio_format_t encodedFormat) const
{
- sp<HwModule> hwModule = getModuleForDeviceTypes(type);
+ sp<HwModule> hwModule = getModuleForDeviceTypes(type, encodedFormat);
if (hwModule == 0) {
ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type,
address);
@@ -354,8 +364,9 @@
sp<DeviceDescriptor> device = new DeviceDescriptor(type, String8(name));
device->setName(String8(name));
device->setAddress(String8(address));
+ device->setEncodedFormat(encodedFormat);
- // Add the device to the list of dynamic devices
+ // Add the device to the list of dynamic devices
hwModule->addDynamicDevice(device);
// Reciprocally attach the device to the module
device->attach(hwModule);
@@ -370,7 +381,8 @@
if (profile->supportsDevice(device, false /*matchAdress*/)) {
// @todo quid of audio profile? import the profile from device of the same type?
- const auto &isoTypeDeviceForProfile = profile->getSupportedDevices().getDevice(type);
+ const auto &isoTypeDeviceForProfile =
+ profile->getSupportedDevices().getDevice(type, String8(), AUDIO_FORMAT_DEFAULT);
device->importAudioPort(isoTypeDeviceForProfile, true /* force */);
ALOGV("%s: adding device %s to profile %s", __FUNCTION__,
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 1154654..98d375c 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -140,6 +140,8 @@
static constexpr const char *roleSource = "source"; /**< <attribute role source value>. */
/** optional: device address, char string less than 64. */
static constexpr const char *address = "address";
+ /** optional: the list of encoded audio formats that are known to be supported. */
+ static constexpr const char *encodedFormats = "encodedFormats";
};
static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
@@ -511,7 +513,13 @@
ALOGW("%s: bad type %08x", __func__, type);
return Status::fromStatusT(BAD_VALUE);
}
- Element deviceDesc = new DeviceDescriptor(type, String8(name.c_str()));
+ std::string encodedFormatsLiteral = getXmlAttribute(cur, Attributes::encodedFormats);
+ ALOGV("%s: %s %s=%s", __func__, tag, Attributes::encodedFormats, encodedFormatsLiteral.c_str());
+ FormatVector encodedFormats;
+ if (!encodedFormatsLiteral.empty()) {
+ encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
+ }
+ Element deviceDesc = new DeviceDescriptor(type, encodedFormats, String8(name.c_str()));
std::string address = getXmlAttribute(cur, Attributes::address);
if (!address.empty()) {
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 3d68cd8..cc5a025 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -506,7 +506,7 @@
if (strategy != STRATEGY_SONIFICATION) {
// no sonification on remote submix (e.g. WFD)
if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- String8("0")) != 0) {
+ String8("0"), AUDIO_FORMAT_DEFAULT) != 0) {
device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 5c8a799..a03e20d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -81,9 +81,11 @@
status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
- status_t status = setDeviceConnectionStateInt(device, state, device_address, device_name);
+ status_t status = setDeviceConnectionStateInt(device, state, device_address,
+ device_name, encodedFormat);
nextAudioPortGeneration();
return status;
}
@@ -101,16 +103,17 @@
status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceType,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
- ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s",
- deviceType, state, device_address, device_name);
+ ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s format 0x%X",
+ deviceType, state, device_address, device_name, encodedFormat);
// connect/disconnect only 1 device at a time
if (!audio_is_output_device(deviceType) && !audio_is_input_device(deviceType)) return BAD_VALUE;
sp<DeviceDescriptor> device =
- mHwModules.getDeviceDescriptor(deviceType, device_address, device_name,
+ mHwModules.getDeviceDescriptor(deviceType, device_address, device_name, encodedFormat,
state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
if (device == 0) {
return INVALID_OPERATION;
@@ -133,10 +136,22 @@
ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
return INVALID_OPERATION;
}
- ALOGV("%s() connecting device %s", __func__, device->toString().c_str());
+ ALOGV("%s() connecting device %s format %x",
+ __func__, device->toString().c_str(), encodedFormat);
// register new device as available
- if (mAvailableOutputDevices.add(device) < 0) {
+ index = mAvailableOutputDevices.add(device);
+ if (index >= 0) {
+ sp<HwModule> module = mHwModules.getModuleForDevice(device, encodedFormat);
+ if (module == 0) {
+ ALOGD("setDeviceConnectionState() could not find HW module for device %s",
+ device->toString().c_str());
+ mAvailableOutputDevices.remove(device);
+ return INVALID_OPERATION;
+ }
+ ALOGV("setDeviceConnectionState() module name=%s", module->getName());
+ mAvailableOutputDevices[index]->attach(module);
+ } else {
return NO_MEMORY;
}
@@ -178,6 +193,9 @@
checkOutputsForDevice(device, state, outputs);
+ // Reset active device codec
+ device->setEncodedFormat(AUDIO_FORMAT_DEFAULT);
+
// Propagate device availability to Engine
mEngine->setDeviceConnectionState(device, state);
} break;
@@ -248,6 +266,13 @@
ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
return INVALID_OPERATION;
}
+ sp<HwModule> module = mHwModules.getModuleForDevice(device, AUDIO_FORMAT_DEFAULT);
+ if (module == NULL) {
+ ALOGW("setDeviceConnectionState(): could not find HW module for device %s",
+ device->toString().c_str());
+ return INVALID_OPERATION;
+ }
+
// 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);
@@ -318,7 +343,8 @@
const char *device_address)
{
sp<DeviceDescriptor> devDesc =
- mHwModules.getDeviceDescriptor(device, device_address, "", false /* allowToCreate */,
+ mHwModules.getDeviceDescriptor(device, device_address, "", AUDIO_FORMAT_DEFAULT,
+ false /* allowToCreate */,
(strlen(device_address) != 0)/*matchAddress*/);
if (devDesc == 0) {
@@ -338,50 +364,61 @@
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
- return (deviceVector->getDevice(device, String8(device_address)) != 0) ?
+ return (deviceVector->getDevice(
+ device, String8(device_address), AUDIO_FORMAT_DEFAULT) != 0) ?
AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
status_t AudioPolicyManager::handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
status_t status;
String8 reply;
AudioParameter param;
int isReconfigA2dpSupported = 0;
- ALOGV("handleDeviceConfigChange(() device: 0x%X, address %s name %s",
- device, device_address, device_name);
+ ALOGV("handleDeviceConfigChange(() device: 0x%X, address %s name %s encodedFormat: 0x%X",
+ device, device_address, device_name, encodedFormat);
// connect/disconnect only 1 device at a time
if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
// Check if the device is currently connected
- sp<DeviceDescriptor> devDesc =
- mHwModules.getDeviceDescriptor(device, device_address, device_name);
- if (devDesc == 0 || mAvailableOutputDevices.indexOf(devDesc) < 0) {
+ DeviceVector availableDevices = getAvailableOutputDevices();
+ DeviceVector deviceList = availableDevices.getDevicesFromTypeMask(device);
+ if (deviceList.empty()) {
// Nothing to do: device is not connected
return NO_ERROR;
}
+ sp<DeviceDescriptor> devDesc = deviceList.itemAt(0);
// For offloaded A2DP, Hw modules may have the capability to
- // configure codecs. Check if any of the loaded hw modules
- // supports this.
- // If supported, send a set parameter to configure A2DP codecs
- // and return. No need to toggle device state.
+ // configure codecs.
+ // Handle two specific cases by sending a set parameter to
+ // configure A2DP codecs. No need to toggle device state.
+ // Case 1: A2DP active device switches from primary to primary
+ // module
+ // Case 2: A2DP device config changes on primary module.
if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
- reply = mpClientInterface->getParameters(
- AUDIO_IO_HANDLE_NONE,
- String8(AudioParameter::keyReconfigA2dpSupported));
- AudioParameter repliedParameters(reply);
- repliedParameters.getInt(
- String8(AudioParameter::keyReconfigA2dpSupported), isReconfigA2dpSupported);
- if (isReconfigA2dpSupported) {
- const String8 key(AudioParameter::keyReconfigA2dp);
- param.add(key, String8("true"));
- mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
- return NO_ERROR;
+ sp<HwModule> module = mHwModules.getModuleForDeviceTypes(device, encodedFormat);
+ audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
+ if (availablePrimaryOutputDevices().contains(devDesc) &&
+ (module != 0 && module->getHandle() == primaryHandle)) {
+ reply = mpClientInterface->getParameters(
+ AUDIO_IO_HANDLE_NONE,
+ String8(AudioParameter::keyReconfigA2dpSupported));
+ AudioParameter repliedParameters(reply);
+ repliedParameters.getInt(
+ String8(AudioParameter::keyReconfigA2dpSupported), isReconfigA2dpSupported);
+ if (isReconfigA2dpSupported) {
+ const String8 key(AudioParameter::keyReconfigA2dp);
+ param.add(key, String8("true"));
+ mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+ devDesc->setEncodedFormat(encodedFormat);
+ return NO_ERROR;
+ }
}
}
@@ -389,7 +426,8 @@
// This will force reading again the device configuration
status = setDeviceConnectionState(device,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- device_address, device_name);
+ device_address, device_name,
+ devDesc->getEncodedFormat());
if (status != NO_ERROR) {
ALOGW("handleDeviceConfigChange() error disabling connection state: %d",
status);
@@ -398,7 +436,7 @@
status = setDeviceConnectionState(device,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- device_address, device_name);
+ device_address, device_name, encodedFormat);
if (status != NO_ERROR) {
ALOGW("handleDeviceConfigChange() error enabling connection state: %d",
status);
@@ -464,15 +502,18 @@
}
if (isRx) {
patchBuilder.addSink(device).
- addSource(mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX));
+ addSource(mAvailableInputDevices.getDevice(
+ AUDIO_DEVICE_IN_TELEPHONY_RX, String8(), AUDIO_FORMAT_DEFAULT));
} else {
patchBuilder.addSource(device).
- addSink(mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX));
+ addSink(mAvailableOutputDevices.getDevice(
+ AUDIO_DEVICE_OUT_TELEPHONY_TX, String8(), AUDIO_FORMAT_DEFAULT));
}
// @TODO: still ignoring the address, or not dealing platform with mutliple telephonydevices
const sp<DeviceDescriptor> outputDevice = isRx ?
- device : mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX);
+ device : mAvailableOutputDevices.getDevice(
+ AUDIO_DEVICE_OUT_TELEPHONY_TX, String8(), AUDIO_FORMAT_DEFAULT);
SortedVector<audio_io_handle_t> outputs =
getOutputsForDevices(DeviceVector(outputDevice), mOutputs);
audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID);
@@ -736,6 +777,10 @@
if (!mAvailableOutputDevices.containsAtLeastOne(curProfile->getSupportedDevices())) {
continue;
}
+ // reject profiles if connected device does not support codec
+ if (!curProfile->deviceSupportsEncodedFormats(devices.types())) {
+ continue;
+ }
if (!directOnly) return curProfile;
// when searching for direct outputs, if several profiles are compatible, give priority
// to one with offload capability
@@ -840,7 +885,8 @@
*output = desc->mIoHandle;
AudioMix *mix = desc->mPolicyMix;
sp<DeviceDescriptor> deviceDesc =
- mAvailableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress);
+ mAvailableOutputDevices.getDevice(
+ mix->mDeviceType, mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT);
*selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
ALOGV("%s returns output %d", __func__, *output);
return NO_ERROR;
@@ -883,7 +929,8 @@
*output = AUDIO_IO_HANDLE_NONE;
if (!msdDevices.isEmpty()) {
*output = getOutputForDevices(msdDevices, session, *stream, config, flags);
- sp<DeviceDescriptor> deviceDesc = mAvailableOutputDevices.getDevice(deviceType);
+ sp<DeviceDescriptor> deviceDesc =
+ mAvailableOutputDevices.getDevice(deviceType, String8(), AUDIO_FORMAT_DEFAULT);
if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(deviceDesc) == NO_ERROR) {
ALOGV("%s() Using MSD devices %s instead of device %s",
__func__, msdDevices.toString().c_str(), deviceDesc->toString().c_str());
@@ -1158,7 +1205,7 @@
ALOGE("%s() unable to get MSD module", __func__);
return NO_INIT;
}
- sp<HwModule> deviceModule = mHwModules.getModuleForDevice(outputDevice);
+ sp<HwModule> deviceModule = mHwModules.getModuleForDevice(outputDevice, AUDIO_FORMAT_DEFAULT);
if (deviceModule == nullptr) {
ALOGE("%s() unable to get module for %s", __func__, outputDevice->toString().c_str());
return NO_INIT;
@@ -1456,7 +1503,8 @@
} else {
newDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
- devices.add(mAvailableOutputDevices.getDevice(newDeviceType, String8(address)));
+ devices.add(mAvailableOutputDevices.getDevice(newDeviceType,
+ String8(address), AUDIO_FORMAT_DEFAULT));
}
// requiresMuteCheck is false when we can bypass mute strategy.
@@ -1574,7 +1622,8 @@
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address,
- "remote-submix");
+ "remote-submix",
+ AUDIO_FORMAT_DEFAULT);
}
return NO_ERROR;
@@ -1620,7 +1669,7 @@
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
outputDesc->mPolicyMix->mDeviceAddress,
- "remote-submix");
+ "remote-submix", AUDIO_FORMAT_DEFAULT);
}
}
bool forceDeviceUpdate = false;
@@ -1812,7 +1861,8 @@
}
*inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- String8(attr->tags + strlen("addr=")));
+ String8(attr->tags + strlen("addr=")),
+ AUDIO_FORMAT_DEFAULT);
} else {
if (explicitRoutingDevice != nullptr) {
device = explicitRoutingDevice;
@@ -1831,7 +1881,8 @@
// know about it and is therefore considered "legacy"
*inputType = API_INPUT_LEGACY;
} else if (audio_is_remote_submix_device(device->type())) {
- device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8("0"));
+ device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8("0"),
+ AUDIO_FORMAT_DEFAULT);
*inputType = API_INPUT_MIX_CAPTURE;
} else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) {
*inputType = API_INPUT_TELEPHONY_RX;
@@ -2065,7 +2116,7 @@
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address, "remote-submix");
+ address, "remote-submix", AUDIO_FORMAT_DEFAULT);
}
}
}
@@ -2116,7 +2167,7 @@
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address, "remote-submix");
+ address, "remote-submix", AUDIO_FORMAT_DEFAULT);
}
}
resetInputDevice(input);
@@ -2536,11 +2587,11 @@
if (mix.mMixType == MIX_TYPE_PLAYERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix");
+ address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT);
} else {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix");
+ address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT);
}
} else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
String8 address = mix.mDeviceAddress;
@@ -2614,13 +2665,13 @@
AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string(), "remote-submix");
+ address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT);
}
if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string(), "remote-submix");
+ address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT);
}
rSubmixModule->removeOutputProfile(address);
rSubmixModule->removeInputProfile(address);
@@ -2664,7 +2715,8 @@
// reevaluate outputs for all given devices
for (size_t i = 0; i < devices.size(); i++) {
sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
- devices[i].mType, devices[i].mAddress, String8());
+ devices[i].mType, devices[i].mAddress, String8(),
+ AUDIO_FORMAT_DEFAULT);
SortedVector<audio_io_handle_t> outputs;
if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
outputs) != NO_ERROR) {
@@ -2685,7 +2737,8 @@
// reevaluate outputs for all found devices
for (size_t i = 0; i < devices.size(); i++) {
sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
- devices[i].mType, devices[i].mAddress, String8());
+ devices[i].mType, devices[i].mAddress, String8(),
+ AUDIO_FORMAT_DEFAULT);
SortedVector<audio_io_handle_t> outputs;
if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
outputs) != NO_ERROR) {
@@ -3442,7 +3495,8 @@
sp<DeviceDescriptor> srcDevice =
mAvailableInputDevices.getDevice(source->ext.device.type,
- String8(source->ext.device.address));
+ String8(source->ext.device.address),
+ AUDIO_FORMAT_DEFAULT);
if (srcDevice == 0) {
ALOGW("%s source->ext.device.type %08x not found", __FUNCTION__, source->ext.device.type);
return BAD_VALUE;
@@ -3726,14 +3780,16 @@
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
address.c_str(),
- name.c_str());
+ name.c_str(),
+ AUDIO_FORMAT_DEFAULT);
if (status != NO_ERROR) {
continue;
}
status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address.c_str(),
- name.c_str());
+ name.c_str(),
+ AUDIO_FORMAT_DEFAULT);
profileUpdated |= (status == NO_ERROR);
}
// FIXME: Why doing this for input HDMI devices if we don't augment their reported formats?
@@ -3746,14 +3802,16 @@
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
address.c_str(),
- name.c_str());
+ name.c_str(),
+ AUDIO_FORMAT_DEFAULT);
if (status != NO_ERROR) {
continue;
}
status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address.c_str(),
- name.c_str());
+ name.c_str(),
+ AUDIO_FORMAT_DEFAULT);
profileUpdated |= (status == NO_ERROR);
}
@@ -4178,7 +4236,8 @@
// first list already open outputs that can be routed to this device
for (size_t i = 0; i < mOutputs.size(); i++) {
desc = mOutputs.valueAt(i);
- if (!desc->isDuplicated() && desc->supportsDevice(device)) {
+ if (!desc->isDuplicated() && desc->supportsDevice(device)
+ && desc->deviceSupportsEncodedFormats(deviceType)) {
ALOGV("checkOutputsForDevice(): adding opened output %d on device %s",
mOutputs.keyAt(i), device->toString().c_str());
outputs.add(mOutputs.keyAt(i));
@@ -4341,7 +4400,8 @@
desc = mOutputs.valueAt(i);
if (!desc->isDuplicated()) {
// exact match on device
- if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)) {
+ if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
+ && desc->deviceSupportsEncodedFormats(deviceType)) {
outputs.add(mOutputs.keyAt(i));
} else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
@@ -4628,7 +4688,8 @@
ALOGVV("output %zu isDuplicated=%d device=%s",
i, openOutputs.valueAt(i)->isDuplicated(),
openOutputs.valueAt(i)->supportedDevices().toString().c_str());
- if (openOutputs.valueAt(i)->supportsAllDevices(devices)) {
+ if (openOutputs.valueAt(i)->supportsAllDevices(devices)
+ && openOutputs.valueAt(i)->deviceSupportsEncodedFormats(devices.types())) {
ALOGVV("%s() found output %d", __func__, openOutputs.keyAt(i));
outputs.add(openOutputs.keyAt(i));
}
@@ -4684,9 +4745,10 @@
maxLatency = desc->latency();
}
}
- ALOGV("%s: strategy %d, moving from output %s to output %s", __func__, strategy,
- (srcOutputs.isEmpty()? "none" : std::to_string(srcOutputs[0]).c_str()),
- (dstOutputs.isEmpty()? "none" : std::to_string(dstOutputs[0]).c_str()));
+ ALOGV_IF(!(srcOutputs.isEmpty() || dstOutputs.isEmpty()),
+ "%s: strategy %d, moving from output %s to output %s", __func__, strategy,
+ std::to_string(srcOutputs[0]).c_str(),
+ std::to_string(dstOutputs[0]).c_str());
// mute strategy while moving tracks from one output to another
for (audio_io_handle_t srcOut : srcOutputs) {
sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
@@ -5404,9 +5466,10 @@
if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX &&
strncmp(attributes.tags, "addr=", strlen("addr=")) == 0) {
return mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- String8(attributes.tags + strlen("addr=")));
+ String8(attributes.tags + strlen("addr=")),
+ AUDIO_FORMAT_DEFAULT);
}
- return mAvailableInputDevices.getDevice(device);
+ return mAvailableInputDevices.getDevice(device, String8(), AUDIO_FORMAT_DEFAULT);
}
float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index e99de16..4b42a34 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -97,12 +97,14 @@
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name);
+ const char *device_name,
+ audio_format_t encodedFormat);
virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address);
virtual status_t handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name);
+ const char *device_name,
+ audio_format_t encodedFormat);
virtual void setPhoneState(audio_mode_t state);
virtual void setForceUse(audio_policy_force_use_t usage,
audio_policy_forced_cfg_t config);
@@ -731,7 +733,8 @@
status_t setDeviceConnectionStateInt(audio_devices_t deviceType,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name);
+ const char *device_name,
+ audio_format_t encodedFormat);
void updateMono(audio_io_handle_t output) {
AudioParameter param;
param.addInt(String8(AudioParameter::keyMonoOutput), (int)mMasterMono);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 2c904d9..09168f4 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -32,7 +32,8 @@
status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
@@ -49,7 +50,7 @@
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
return mAudioPolicyManager->setDeviceConnectionState(device, state,
- device_address, device_name);
+ device_address, device_name, encodedFormat);
}
audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
@@ -66,7 +67,8 @@
status_t AudioPolicyService::handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name)
+ const char *device_name,
+ audio_format_t encodedFormat)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
@@ -79,7 +81,7 @@
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
return mAudioPolicyManager->handleDeviceConfigChange(device, device_address,
- device_name);
+ device_name, encodedFormat);
}
status_t AudioPolicyService::setPhoneState(audio_mode_t state)
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 959e757..6ff973e 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -61,13 +61,15 @@
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
- const char *device_name);
+ const char *device_name,
+ audio_format_t encodedFormat);
virtual audio_policy_dev_state_t getDeviceConnectionState(
audio_devices_t device,
const char *device_address);
virtual status_t handleDeviceConfigChange(audio_devices_t device,
const char *device_address,
- const char *device_name);
+ const char *device_name,
+ audio_format_t encodedFormat);
virtual status_t setPhoneState(audio_mode_t state);
virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);