summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-03-17 12:00:47 -0700
committerEric Laurent <elaurent@google.com>2014-03-26 15:28:33 -0700
commit3a4311c68348f728558e87b5db67d47605783890 (patch)
tree920ecdf2868176572b6770200d6e3314c5462dd7 /services/audiopolicy
parent172a7a965c21c29ee38c77d53d91780c7dca09bf (diff)
downloadframeworks_av-3a4311c68348f728558e87b5db67d47605783890.zip
frameworks_av-3a4311c68348f728558e87b5db67d47605783890.tar.gz
frameworks_av-3a4311c68348f728558e87b5db67d47605783890.tar.bz2
audio policy: use new audio device representation
Represent audio devices with more attributes than just the type (audio_device_t). This is in preparation for new routing APIs allowing device selection based on more criteria than just the type (address, channel mask...) A new class DeviceDescriptor is created and used by functions needing more information than just the device type. Bit fields for available and supported input or output devices are replaced by vectors of device descriptors. Each available device is allocated a unique ID for future use. Removed obsolete mA2dpDeviceAddress, mScoDeviceAddress and mUsbCardAndDevice fields replaced by address stored in DeviceDescriptor. Policy decisions like getDeviceForStrategy() are still based only on the device type. Change-Id: I5de3b3ffb12ff8dcfb746782ab1e6b15bf040d0c
Diffstat (limited to 'services/audiopolicy')
-rw-r--r--services/audiopolicy/AudioPolicyManager.cpp764
-rw-r--r--services/audiopolicy/AudioPolicyManager.h66
2 files changed, 549 insertions, 281 deletions
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 5ac9d9e..eeba124 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -43,6 +43,117 @@
namespace android {
// ----------------------------------------------------------------------------
+// Definitions for audio_policy.conf file parsing
+// ----------------------------------------------------------------------------
+
+struct StringToEnum {
+ const char *name;
+ uint32_t value;
+};
+
+#define STRING_TO_ENUM(string) { #string, string }
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+const StringToEnum sDeviceNameToEnumTable[] = {
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
+};
+
+const StringToEnum sFlagNameToEnumTable[] = {
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+};
+
+const StringToEnum sFormatNameToEnumTable[] = {
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_FLOAT),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
+ STRING_TO_ENUM(AUDIO_FORMAT_MP3),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC),
+ STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
+};
+
+const StringToEnum sOutChannelsNameToEnumTable[] = {
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_MONO),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+};
+
+const StringToEnum sInChannelsNameToEnumTable[] = {
+ STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
+ STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
+ STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
+};
+
+
+uint32_t AudioPolicyManager::stringToEnum(const struct StringToEnum *table,
+ size_t size,
+ const char *name)
+{
+ for (size_t i = 0; i < size; i++) {
+ if (strcmp(table[i].name, name) == 0) {
+ ALOGV("stringToEnum() found %s", table[i].name);
+ return table[i].value;
+ }
+ }
+ return 0;
+}
+
+const char *AudioPolicyManager::enumToString(const struct StringToEnum *table,
+ size_t size,
+ uint32_t value)
+{
+ for (size_t i = 0; i < size; i++) {
+ if (table[i].value == value) {
+ return table[i].name;
+ }
+ }
+ return "";
+}
+
+bool AudioPolicyManager::stringToBool(const char *value)
+{
+ return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0));
+}
+
+
+// ----------------------------------------------------------------------------
// AudioPolicyInterface implementation
// ----------------------------------------------------------------------------
@@ -52,6 +163,7 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
const char *device_address)
{
SortedVector <audio_io_handle_t> outputs;
+ String8 address = String8(device_address);
ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
@@ -79,74 +191,50 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
return BAD_VALUE;
}
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device,
+ address,
+ AUDIO_CHANNEL_NONE);
+ ssize_t index = mAvailableOutputDevices.indexOf(devDesc);
+
// save a copy of the opened output descriptors before any output is opened or closed
// by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies()
mPreviousOutputs = mOutputs;
- String8 paramStr;
switch (state)
{
// handle output device connection
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE:
- if (mAvailableOutputDevices & device) {
+ if (index >= 0) {
ALOGW("setDeviceConnectionState() device already connected: %x", device);
return INVALID_OPERATION;
}
ALOGV("setDeviceConnectionState() connecting device %x", device);
- if (mHasA2dp && audio_is_a2dp_device(device)) {
- // handle A2DP device connection
- AudioParameter param;
- param.add(String8(AUDIO_PARAMETER_A2DP_SINK_ADDRESS), String8(device_address));
- paramStr = param.toString();
- } else if (mHasUsb && audio_is_usb_device(device)) {
- // handle USB device connection
- paramStr = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
- }
-
- if (checkOutputsForDevice(device, state, outputs, paramStr) != NO_ERROR) {
+ if (checkOutputsForDevice(device, state, outputs, address) != NO_ERROR) {
return INVALID_OPERATION;
}
ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %d outputs",
outputs.size());
// register new device as available
- mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | device);
-
- if (mHasA2dp && audio_is_a2dp_device(device)) {
- // handle A2DP device connection
- mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
- mA2dpSuspended = false;
- } else if (audio_is_bluetooth_sco_device(device)) {
- // handle SCO device connection
- mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
- } else if (mHasUsb && audio_is_usb_device(device)) {
- // handle USB device connection
- mUsbCardAndDevice = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
+ index = mAvailableOutputDevices.add(devDesc);
+ if (index >= 0) {
+ mAvailableOutputDevices[index]->mId = nextUniqueId();
+ } else {
+ return NO_MEMORY;
}
break;
// handle output device disconnection
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
- if (!(mAvailableOutputDevices & device)) {
+ if (index < 0) {
ALOGW("setDeviceConnectionState() device not connected: %x", device);
return INVALID_OPERATION;
}
ALOGV("setDeviceConnectionState() disconnecting device %x", device);
// remove device from available output devices
- mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device);
-
- checkOutputsForDevice(device, state, outputs, paramStr);
- if (mHasA2dp && audio_is_a2dp_device(device)) {
- // handle A2DP device disconnection
- mA2dpDeviceAddress = "";
- mA2dpSuspended = false;
- } else if (audio_is_bluetooth_sco_device(device)) {
- // handle SCO device disconnection
- mScoDeviceAddress = "";
- } else if (mHasUsb && audio_is_usb_device(device)) {
- // handle USB device disconnection
- mUsbCardAndDevice = "";
- }
+ mAvailableOutputDevices.remove(devDesc);
+
+ checkOutputsForDevice(device, state, outputs, address);
// not currently handling multiple simultaneous submixes: ignoring remote submix
// case and address
} break;
@@ -156,6 +244,8 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
return BAD_VALUE;
}
+ // checkA2dpSuspend must run before checkOutputForAllStrategies so that A2DP
+ // output is suspended before any tracks are moved to it
checkA2dpSuspend();
checkOutputForAllStrategies();
// outputs must be closed after checkOutputForAllStrategies() is executed
@@ -170,6 +260,8 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
closeOutput(outputs[i]);
}
}
+ // check again after closing A2DP output to reset mA2dpSuspended if needed
+ checkA2dpSuspend();
}
updateDevicesAndOutputs();
@@ -195,26 +287,35 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
}
// handle input devices
if (audio_is_input_device(device)) {
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device,
+ address,
+ AUDIO_CHANNEL_NONE);
+ ssize_t index = mAvailableInputDevices.indexOf(devDesc);
switch (state)
{
// handle input device connection
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
- if (mAvailableInputDevices & device) {
+ if (index >= 0) {
ALOGW("setDeviceConnectionState() device already connected: %d", device);
return INVALID_OPERATION;
}
- mAvailableInputDevices = mAvailableInputDevices | (device & ~AUDIO_DEVICE_BIT_IN);
+ index = mAvailableInputDevices.add(devDesc);
+ if (index >= 0) {
+ mAvailableInputDevices[index]->mId = nextUniqueId();
+ } else {
+ return NO_MEMORY;
+ }
}
break;
// handle input device disconnection
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
- if (!(mAvailableInputDevices & device)) {
+ if (index < 0) {
ALOGW("setDeviceConnectionState() device not connected: %d", device);
return INVALID_OPERATION;
}
- mAvailableInputDevices = (audio_devices_t) (mAvailableInputDevices & ~device);
+ mAvailableInputDevices.remove(devDesc);
} break;
default:
@@ -248,33 +349,27 @@ audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devi
{
audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
String8 address = String8(device_address);
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device,
+ String8(device_address),
+ AUDIO_CHANNEL_NONE);
+ ssize_t index;
+ DeviceVector *deviceVector;
+
if (audio_is_output_device(device)) {
- if (device & mAvailableOutputDevices) {
- if (audio_is_a2dp_device(device) &&
- (!mHasA2dp || (address != "" && mA2dpDeviceAddress != address))) {
- return state;
- }
- if (audio_is_bluetooth_sco_device(device) &&
- address != "" && mScoDeviceAddress != address) {
- return state;
- }
- if (audio_is_usb_device(device) &&
- (!mHasUsb || (address != "" && mUsbCardAndDevice != address))) {
- ALOGE("getDeviceConnectionState() invalid device: %x", device);
- return state;
- }
- if (audio_is_remote_submix_device((audio_devices_t)device) && !mHasRemoteSubmix) {
- return state;
- }
- state = AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
- }
+ deviceVector = &mAvailableOutputDevices;
} else if (audio_is_input_device(device)) {
- if (device & mAvailableInputDevices) {
- state = AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
- }
+ deviceVector = &mAvailableInputDevices;
+ } else {
+ ALOGW("getDeviceConnectionState() invalid device type %08x", device);
+ return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
- return state;
+ index = deviceVector->indexOf(devDesc);
+ if (index >= 0) {
+ return AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
+ } else {
+ return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+ }
}
void AudioPolicyManager::setPhoneState(audio_mode_t state)
@@ -505,23 +600,23 @@ AudioPolicyManager::IOProfile *AudioPolicyManager::getProfileForDirectOutput(
}
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) {
IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
+ bool found = false;
if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
if (profile->isCompatibleProfile(device, samplingRate, format,
channelMask,
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
- if (mAvailableOutputDevices & profile->mSupportedDevices) {
- return mHwModules[i]->mOutputProfiles[j];
- }
+ found = true;
}
} else {
if (profile->isCompatibleProfile(device, samplingRate, format,
channelMask,
AUDIO_OUTPUT_FLAG_DIRECT)) {
- if (mAvailableOutputDevices & profile->mSupportedDevices) {
- return mHwModules[i]->mOutputProfiles[j];
- }
+ found = true;
}
}
+ if (found && (mAvailableOutputDevices.types() & profile->mSupportedDevices.types())) {
+ return profile;
+ }
}
}
return 0;
@@ -1377,16 +1472,6 @@ status_t AudioPolicyManager::dump(int fd)
snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput);
result.append(buffer);
- snprintf(buffer, SIZE, " A2DP device address: %s\n", mA2dpDeviceAddress.string());
- result.append(buffer);
- snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string());
- result.append(buffer);
- snprintf(buffer, SIZE, " USB audio ALSA %s\n", mUsbCardAndDevice.string());
- result.append(buffer);
- snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
- result.append(buffer);
- snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
- result.append(buffer);
snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
result.append(buffer);
snprintf(buffer, SIZE, " Force use for communications %d\n",
@@ -1400,8 +1485,20 @@ status_t AudioPolicyManager::dump(int fd)
result.append(buffer);
snprintf(buffer, SIZE, " Force use for system %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM]);
result.append(buffer);
- write(fd, result.string(), result.size());
+ snprintf(buffer, SIZE, " Available output devices:\n");
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ DeviceDescriptor::dumpHeader(fd, 2);
+ for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
+ mAvailableOutputDevices[i]->dump(fd, 2);
+ }
+ snprintf(buffer, SIZE, "\n Available input devices:\n");
+ write(fd, buffer, strlen(buffer));
+ DeviceDescriptor::dumpHeader(fd, 2);
+ for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
+ mAvailableInputDevices[i]->dump(fd, 2);
+ }
snprintf(buffer, SIZE, "\nHW Modules dump:\n");
write(fd, buffer, strlen(buffer));
@@ -1525,18 +1622,22 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI
// AudioPolicyManager
// ----------------------------------------------------------------------------
+uint32_t AudioPolicyManager::nextUniqueId()
+{
+ return android_atomic_inc(&mNextUniqueId);
+}
+
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
:
#ifdef AUDIO_POLICY_TEST
Thread(false),
#endif //AUDIO_POLICY_TEST
mPrimaryOutput((audio_io_handle_t)0),
- mAvailableOutputDevices(AUDIO_DEVICE_NONE),
mPhoneState(AUDIO_MODE_NORMAL),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
- mA2dpSuspended(false), mHasA2dp(false), mHasUsb(false), mHasRemoteSubmix(false),
- mSpeakerDrcEnabled(false)
+ mA2dpSuspended(false),
+ mSpeakerDrcEnabled(false), mNextUniqueId(0)
{
mpClientInterface = clientInterface;
@@ -1544,21 +1645,21 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
}
- mA2dpDeviceAddress = String8("");
- mScoDeviceAddress = String8("");
- mUsbCardAndDevice = String8("");
-
+ mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
ALOGE("could not load audio policy configuration file, setting defaults");
defaultAudioPolicyConfig();
}
}
+ // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
// must be done after reading the policy
initializeVolumeCurves();
// open all output streams needed to access attached devices
+ audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
+ audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
for (size_t i = 0; i < mHwModules.size(); i++) {
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
if (mHwModules[i]->mHandle == 0) {
@@ -1568,15 +1669,22 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
// open all output streams needed to access attached devices
// except for direct output streams that are only opened when they are actually
// required by an app.
+ // This also validates mAvailableOutputDevices list
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j];
- if ((outProfile->mSupportedDevices & mAttachedOutputDevices) &&
+ if (outProfile->mSupportedDevices.isEmpty()) {
+ ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName);
+ continue;
+ }
+
+ audio_devices_t profileTypes = outProfile->mSupportedDevices.types();
+ if ((profileTypes & outputDeviceTypes) &&
((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile);
- outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice &
- outProfile->mSupportedDevices);
+
+ outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice->mType & profileTypes);
audio_io_handle_t output = mpClientInterface->openOutput(
outProfile->mModule->mHandle,
&outputDesc->mDevice,
@@ -1586,27 +1694,96 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
&outputDesc->mLatency,
outputDesc->mFlags);
if (output == 0) {
+ ALOGW("Cannot open output stream for device %08x on hw module %s",
+ outputDesc->mDevice,
+ mHwModules[i]->mName);
delete outputDesc;
} else {
- mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices |
- (outProfile->mSupportedDevices & mAttachedOutputDevices));
+ for (size_t i = 0; i < outProfile->mSupportedDevices.size(); i++) {
+ audio_devices_t type = outProfile->mSupportedDevices[i]->mType;
+ ssize_t index =
+ mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[i]);
+ // give a valid ID to an attached device once confirmed it is reachable
+ if ((index >= 0) && (mAvailableOutputDevices[index]->mId == 0)) {
+ mAvailableOutputDevices[index]->mId = nextUniqueId();
+ }
+ }
if (mPrimaryOutput == 0 &&
outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = output;
}
addOutput(output, outputDesc);
setOutputDevice(output,
- (audio_devices_t)(mDefaultOutputDevice &
- outProfile->mSupportedDevices),
+ outputDesc->mDevice,
true);
}
}
}
- }
+ // open input streams needed to access attached devices to validate
+ // mAvailableInputDevices list
+ for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)
+ {
+ const IOProfile *inProfile = mHwModules[i]->mInputProfiles[j];
+
+ if (inProfile->mSupportedDevices.isEmpty()) {
+ ALOGW("Input profile contains no device on module %s", mHwModules[i]->mName);
+ continue;
+ }
- ALOGE_IF((mAttachedOutputDevices & ~mAvailableOutputDevices),
- "Not output found for attached devices %08x",
- (mAttachedOutputDevices & ~mAvailableOutputDevices));
+ audio_devices_t profileTypes = inProfile->mSupportedDevices.types();
+ if (profileTypes & inputDeviceTypes) {
+ AudioInputDescriptor *inputDesc = new AudioInputDescriptor(inProfile);
+
+ inputDesc->mInputSource = AUDIO_SOURCE_MIC;
+ inputDesc->mDevice = inProfile->mSupportedDevices[0]->mType;
+ audio_io_handle_t input = mpClientInterface->openInput(
+ inProfile->mModule->mHandle,
+ &inputDesc->mDevice,
+ &inputDesc->mSamplingRate,
+ &inputDesc->mFormat,
+ &inputDesc->mChannelMask);
+
+ if (input != 0) {
+ for (size_t i = 0; i < inProfile->mSupportedDevices.size(); i++) {
+ audio_devices_t type = inProfile->mSupportedDevices[i]->mType;
+ ssize_t index =
+ mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[i]);
+ // give a valid ID to an attached device once confirmed it is reachable
+ if ((index >= 0) && (mAvailableInputDevices[index]->mId == 0)) {
+ mAvailableInputDevices[index]->mId = nextUniqueId();
+ }
+ }
+ mpClientInterface->closeInput(input);
+ } else {
+ ALOGW("Cannot open input stream for device %08x on hw module %s",
+ inputDesc->mDevice,
+ mHwModules[i]->mName);
+ }
+ delete inputDesc;
+ }
+ }
+ }
+ // make sure all attached devices have been allocated a unique ID
+ for (size_t i = 0; i < mAvailableOutputDevices.size();) {
+ if (mAvailableOutputDevices[i]->mId == 0) {
+ ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mType);
+ mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
+ continue;
+ }
+ i++;
+ }
+ for (size_t i = 0; i < mAvailableInputDevices.size();) {
+ if (mAvailableInputDevices[i]->mId == 0) {
+ ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mType);
+ mAvailableInputDevices.remove(mAvailableInputDevices[i]);
+ continue;
+ }
+ i++;
+ }
+ // make sure default device is reachable
+ if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
+ ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->mType);
+ }
ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
@@ -1653,6 +1830,8 @@ AudioPolicyManager::~AudioPolicyManager()
for (size_t i = 0; i < mHwModules.size(); i++) {
delete mHwModules[i];
}
+ mAvailableOutputDevices.clear();
+ mAvailableInputDevices.clear();
}
status_t AudioPolicyManager::initCheck()
@@ -1819,10 +1998,18 @@ void AudioPolicyManager::addOutput(audio_io_handle_t id, AudioOutputDescriptor *
}
+String8 AudioPolicyManager::addressToParameter(audio_devices_t device, const String8 address)
+{
+ if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ return String8("a2dp_sink_address=")+address;
+ }
+ return address;
+}
+
status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& outputs,
- const String8 paramStr)
+ const String8 address)
{
AudioOutputDescriptor *desc;
@@ -1830,7 +2017,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
// 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->mProfile->mSupportedDevices & device)) {
+ if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) {
ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i));
outputs.add(mOutputs.keyAt(i));
}
@@ -1844,7 +2031,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
}
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
- if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices & device) {
+ if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) {
ALOGV("checkOutputsForDevice(): adding profile %d from module %d", j, i);
profiles.add(mHwModules[i]->mOutputProfiles[j]);
}
@@ -1873,7 +2060,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
continue;
}
- ALOGV("opening output for device %08x with params %s", device, paramStr.string());
+ ALOGV("opening output for device %08x with params %s", device, address.string());
desc = new AudioOutputDescriptor(profile);
desc->mDevice = device;
audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
@@ -1890,8 +2077,8 @@ status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
desc->mFlags,
&offloadInfo);
if (output != 0) {
- if (!paramStr.isEmpty()) {
- mpClientInterface->setParameters(output, paramStr);
+ if (!address.isEmpty()) {
+ mpClientInterface->setParameters(output, addressToParameter(device, address));
}
if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
@@ -1991,7 +2178,8 @@ status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
for (size_t i = 0; i < mOutputs.size(); i++) {
desc = mOutputs.valueAt(i);
if (!desc->isDuplicated() &&
- !(desc->mProfile->mSupportedDevices & mAvailableOutputDevices)) {
+ !(desc->mProfile->mSupportedDevices.types() &
+ mAvailableOutputDevices.types())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d", mOutputs.keyAt(i));
outputs.add(mOutputs.keyAt(i));
}
@@ -2004,7 +2192,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
- if ((profile->mSupportedDevices & device) &&
+ if ((profile->mSupportedDevices.types() & device) &&
(profile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
ALOGV("checkOutputsForDevice(): clearing direct output profile %d on module %d",
j, i);
@@ -2187,9 +2375,12 @@ void AudioPolicyManager::checkA2dpSuspend()
}
audio_io_handle_t a2dpOutput = getA2dpOutput();
if (a2dpOutput == 0) {
+ mA2dpSuspended = false;
return;
}
+ bool isScoConnected =
+ (mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0;
// suspend A2DP output if:
// (NOT already suspended) &&
// ((SCO device is connected &&
@@ -2203,7 +2394,7 @@ void AudioPolicyManager::checkA2dpSuspend()
// (phone state is NOT ringing && NOT in call)
//
if (mA2dpSuspended) {
- if (((mScoDeviceAddress == "") ||
+ if ((!isScoConnected ||
((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] != AUDIO_POLICY_FORCE_BT_SCO))) &&
((mPhoneState != AUDIO_MODE_IN_CALL) &&
@@ -2213,7 +2404,7 @@ void AudioPolicyManager::checkA2dpSuspend()
mA2dpSuspended = false;
}
} else {
- if (((mScoDeviceAddress != "") &&
+ if ((isScoConnected &&
((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) ||
(mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO))) ||
((mPhoneState == AUDIO_MODE_IN_CALL) ||
@@ -2328,7 +2519,7 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
strategy, mDeviceForStrategy[strategy]);
return mDeviceForStrategy[strategy];
}
-
+ audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types();
switch (strategy) {
case STRATEGY_SONIFICATION_RESPECTFUL:
@@ -2366,45 +2557,45 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
case AUDIO_POLICY_FORCE_BT_SCO:
if (!isInCall() || strategy != STRATEGY_DTMF) {
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
if (device) break;
}
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
if (device) break;
// if SCO device is requested but no SCO device is available, fall back to default case
// FALL THROUGH
default: // FORCE_NONE
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
- if (mHasA2dp && !isInCall() &&
+ if (!isInCall() &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
(getA2dpOutput() != 0) && !mA2dpSuspended) {
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
if (device) break;
}
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET;
if (device) break;
if (mPhoneState != AUDIO_MODE_IN_CALL) {
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
}
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_EARPIECE;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_EARPIECE;
if (device) break;
- device = mDefaultOutputDevice;
+ device = mDefaultOutputDevice->mType;
if (device == AUDIO_DEVICE_NONE) {
ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
}
@@ -2413,27 +2604,27 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
case AUDIO_POLICY_FORCE_SPEAKER:
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
// A2DP speaker when forcing to speaker output
- if (mHasA2dp && !isInCall() &&
+ if (!isInCall() &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
(getA2dpOutput() != 0) && !mA2dpSuspended) {
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
if (device) break;
}
if (mPhoneState != AUDIO_MODE_IN_CALL) {
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
if (device) break;
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
}
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
if (device) break;
- device = mDefaultOutputDevice;
+ device = mDefaultOutputDevice->mType;
if (device == AUDIO_DEVICE_NONE) {
ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
}
@@ -2459,7 +2650,7 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
if ((strategy == STRATEGY_SONIFICATION) ||
(mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;
+ device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
if (device == AUDIO_DEVICE_NONE) {
ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION");
}
@@ -2471,52 +2662,51 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
uint32_t device2 = AUDIO_DEVICE_NONE;
if (strategy != STRATEGY_SONIFICATION) {
// no sonification on remote submix (e.g. WFD)
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
- mHasA2dp &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
(getA2dpOutput() != 0) && !mA2dpSuspended) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
if (device2 == AUDIO_DEVICE_NONE) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
}
if (device2 == AUDIO_DEVICE_NONE) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
}
}
if (device2 == AUDIO_DEVICE_NONE) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
}
if (device2 == AUDIO_DEVICE_NONE) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
}
if (device2 == AUDIO_DEVICE_NONE) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
}
if (device2 == AUDIO_DEVICE_NONE) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
}
if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
// no sonification on aux digital (e.g. HDMI)
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
- device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;
+ device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
}
// device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
// STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
device |= device2;
if (device) break;
- device = mDefaultOutputDevice;
+ device = mDefaultOutputDevice->mType;
if (device == AUDIO_DEVICE_NONE) {
ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
}
@@ -2630,12 +2820,12 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output,
// no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current
// output profile
if ((device != AUDIO_DEVICE_NONE) &&
- ((device & outputDesc->mProfile->mSupportedDevices) == 0)) {
+ ((device & outputDesc->mProfile->mSupportedDevices.types()) == 0)) {
return 0;
}
// filter devices according to output selected
- device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices);
+ device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices.types());
audio_devices_t prevDevice = outputDesc->mDevice;
@@ -2694,10 +2884,11 @@ AudioPolicyManager::IOProfile *AudioPolicyManager::getInputProfile(audio_devices
audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
{
uint32_t device = AUDIO_DEVICE_NONE;
-
+ audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
+ ~AUDIO_DEVICE_BIT_IN;
switch (inputSource) {
case AUDIO_SOURCE_VOICE_UPLINK:
- if (mAvailableInputDevices & AUDIO_DEVICE_IN_VOICE_CALL) {
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
device = AUDIO_DEVICE_IN_VOICE_CALL;
break;
}
@@ -2709,29 +2900,29 @@ audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t input
case AUDIO_SOURCE_HOTWORD:
case AUDIO_SOURCE_VOICE_COMMUNICATION:
if (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO &&
- mAvailableInputDevices & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
+ availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
- } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_SOURCE_CAMCORDER:
- if (mAvailableInputDevices & AUDIO_DEVICE_IN_BACK_MIC) {
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
device = AUDIO_DEVICE_IN_BACK_MIC;
- } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_SOURCE_VOICE_DOWNLINK:
case AUDIO_SOURCE_VOICE_CALL:
- if (mAvailableInputDevices & AUDIO_DEVICE_IN_VOICE_CALL) {
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
device = AUDIO_DEVICE_IN_VOICE_CALL;
}
break;
case AUDIO_SOURCE_REMOTE_SUBMIX:
- if (mAvailableInputDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
}
break;
@@ -3335,7 +3526,7 @@ audio_devices_t AudioPolicyManager::AudioOutputDescriptor::supportedDevices()
if (isDuplicated()) {
return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices());
} else {
- return mProfile->mSupportedDevices ;
+ return mProfile->mSupportedDevices.types() ;
}
}
@@ -3418,6 +3609,11 @@ AudioPolicyManager::AudioInputDescriptor::AudioInputDescriptor(const IOProfile *
mDevice(AUDIO_DEVICE_NONE), mRefCount(0),
mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile)
{
+ if (profile != NULL) {
+ mSamplingRate = profile->mSamplingRates[0];
+ mFormat = profile->mFormats[0];
+ mChannelMask = profile->mChannelMasks[0];
+ }
}
status_t AudioPolicyManager::AudioInputDescriptor::dump(int fd)
@@ -3512,10 +3708,12 @@ AudioPolicyManager::HwModule::HwModule(const char *name)
AudioPolicyManager::HwModule::~HwModule()
{
for (size_t i = 0; i < mOutputProfiles.size(); i++) {
- delete mOutputProfiles[i];
+ mOutputProfiles[i]->mSupportedDevices.clear();
+ delete mOutputProfiles[i];
}
for (size_t i = 0; i < mInputProfiles.size(); i++) {
- delete mInputProfiles[i];
+ mInputProfiles[i]->mSupportedDevices.clear();
+ delete mInputProfiles[i];
}
free((void *)mName);
}
@@ -3571,7 +3769,7 @@ bool AudioPolicyManager::IOProfile::isCompatibleProfile(audio_devices_t device,
return false;
}
- if ((mSupportedDevices & device) != device) {
+ if ((mSupportedDevices.types() & device) != device) {
return false;
}
if ((mFlags & flags) != flags) {
@@ -3638,103 +3836,129 @@ void AudioPolicyManager::IOProfile::dump(int fd)
result.append(i == (mFormats.size() - 1) ? "\n" : ", ");
}
- snprintf(buffer, SIZE, " - devices: 0x%04x\n", mSupportedDevices);
+ snprintf(buffer, SIZE, " - devices:\n");
result.append(buffer);
+ write(fd, result.string(), result.size());
+ DeviceDescriptor::dumpHeader(fd, 6);
+ for (size_t i = 0; i < mSupportedDevices.size(); i++) {
+ mSupportedDevices[i]->dump(fd, 6);
+ }
+
snprintf(buffer, SIZE, " - flags: 0x%04x\n", mFlags);
result.append(buffer);
write(fd, result.string(), result.size());
}
-// --- audio_policy.conf file parsing
+// --- DeviceDescriptor implementation
-struct StringToEnum {
- const char *name;
- uint32_t value;
-};
-
-#define STRING_TO_ENUM(string) { #string, string }
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+bool AudioPolicyManager::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 or one device does not specify the address
+ // - have the same channel mask or one device does not specify the channel mask
+ return (mType == other->mType) &&
+ (mAddress == "" || other->mAddress == "" || mAddress == other->mAddress) &&
+ (mChannelMask == AUDIO_CHANNEL_NONE || other->mChannelMask == AUDIO_CHANNEL_NONE ||
+ mChannelMask == other->mChannelMask);
+}
-const struct StringToEnum sDeviceNameToEnumTable[] = {
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
- STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
- STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
-};
+void AudioPolicyManager::DeviceVector::refreshTypes()
+{
+ mTypes = AUDIO_DEVICE_NONE;
+ for(size_t i = 0; i < size(); i++) {
+ mTypes |= itemAt(i)->mType;
+ }
+ ALOGV("DeviceVector::refreshTypes() mTypes %08x", mTypes);
+}
-const struct StringToEnum sFlagNameToEnumTable[] = {
- STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
- STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
- STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
- STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
- STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
- STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
-};
+ssize_t AudioPolicyManager::DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
+{
+ for(size_t i = 0; i < size(); i++) {
+ if (item->equals(itemAt(i))) {
+ return i;
+ }
+ }
+ return -1;
+}
-const struct StringToEnum sFormatNameToEnumTable[] = {
- STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
- STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
- STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
- STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
- STRING_TO_ENUM(AUDIO_FORMAT_PCM_FLOAT),
- STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
- STRING_TO_ENUM(AUDIO_FORMAT_MP3),
- STRING_TO_ENUM(AUDIO_FORMAT_AAC),
- STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
-};
+ssize_t AudioPolicyManager::DeviceVector::add(const sp<DeviceDescriptor>& item)
+{
+ ssize_t ret = indexOf(item);
-const struct StringToEnum sOutChannelsNameToEnumTable[] = {
- STRING_TO_ENUM(AUDIO_CHANNEL_OUT_MONO),
- STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
- STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
- STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
-};
+ if (ret < 0) {
+ ret = SortedVector::add(item);
+ if (ret >= 0) {
+ refreshTypes();
+ }
+ } else {
+ ALOGW("DeviceVector::add device %08x already in", item->mType);
+ ret = -1;
+ }
+ return ret;
+}
-const struct StringToEnum sInChannelsNameToEnumTable[] = {
- STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
- STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
- STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
-};
+ssize_t AudioPolicyManager::DeviceVector::remove(const sp<DeviceDescriptor>& item)
+{
+ size_t i;
+ ssize_t ret = indexOf(item);
+ if (ret < 0) {
+ ALOGW("DeviceVector::remove device %08x not in", item->mType);
+ } else {
+ ret = SortedVector::removeAt(ret);
+ if (ret >= 0) {
+ refreshTypes();
+ }
+ }
+ return ret;
+}
-uint32_t AudioPolicyManager::stringToEnum(const struct StringToEnum *table,
- size_t size,
- const char *name)
+void AudioPolicyManager::DeviceVector::loadDevicesFromType(audio_devices_t types)
{
- for (size_t i = 0; i < size; i++) {
- if (strcmp(table[i].name, name) == 0) {
- ALOGV("stringToEnum() found %s", table[i].name);
- return table[i].value;
- }
+ DeviceVector deviceList;
+
+ uint32_t role_bit = AUDIO_DEVICE_BIT_IN & types;
+ types &= ~role_bit;
+
+ while (types) {
+ uint32_t i = 31 - __builtin_clz(types);
+ uint32_t type = 1 << i;
+ types &= ~type;
+ add(new DeviceDescriptor(type | role_bit));
}
- return 0;
}
-bool AudioPolicyManager::stringToBool(const char *value)
+void AudioPolicyManager::DeviceDescriptor::dumpHeader(int fd, int spaces)
{
- return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0));
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "%*s%-48s %-2s %-8s %-32s \n",
+ spaces, "", "Type", "ID", "Cnl Mask", "Address");
+ write(fd, buffer, strlen(buffer));
}
+status_t AudioPolicyManager::DeviceDescriptor::dump(int fd, int spaces) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "%*s%-48s %2d %08x %-32s \n",
+ spaces, "",
+ enumToString(sDeviceNameToEnumTable,
+ ARRAY_SIZE(sDeviceNameToEnumTable),
+ mType),
+ mId, mChannelMask, mAddress.string());
+ write(fd, buffer, strlen(buffer));
+
+ return NO_ERROR;
+}
+
+
+// --- audio_policy.conf file parsing
+
audio_output_flags_t AudioPolicyManager::parseFlagNames(char *name)
{
uint32_t flag = 0;
@@ -3770,9 +3994,9 @@ audio_devices_t AudioPolicyManager::parseDeviceNames(char *name)
device |= stringToEnum(sDeviceNameToEnumTable,
ARRAY_SIZE(sDeviceNameToEnumTable),
devName);
- }
+ }
devName = strtok(NULL, "|");
- }
+ }
return device;
}
@@ -3886,11 +4110,11 @@ status_t AudioPolicyManager::loadInput(cnode *root, HwModule *module)
} else if (strcmp(node->name, CHANNELS_TAG) == 0) {
loadInChannels((char *)node->value, profile);
} else if (strcmp(node->name, DEVICES_TAG) == 0) {
- profile->mSupportedDevices = parseDeviceNames((char *)node->value);
+ profile->mSupportedDevices.loadDevicesFromType(parseDeviceNames((char *)node->value));
}
node = node->next;
}
- ALOGW_IF(profile->mSupportedDevices == AUDIO_DEVICE_NONE,
+ ALOGW_IF(profile->mSupportedDevices.isEmpty(),
"loadInput() invalid supported devices");
ALOGW_IF(profile->mChannelMasks.size() == 0,
"loadInput() invalid supported channel masks");
@@ -3898,12 +4122,13 @@ status_t AudioPolicyManager::loadInput(cnode *root, HwModule *module)
"loadInput() invalid supported sampling rates");
ALOGW_IF(profile->mFormats.size() == 0,
"loadInput() invalid supported formats");
- if ((profile->mSupportedDevices != AUDIO_DEVICE_NONE) &&
+ if (!profile->mSupportedDevices.isEmpty() &&
(profile->mChannelMasks.size() != 0) &&
(profile->mSamplingRates.size() != 0) &&
(profile->mFormats.size() != 0)) {
- ALOGV("loadInput() adding input mSupportedDevices %04x", profile->mSupportedDevices);
+ ALOGV("loadInput() adding input Supported Devices %04x",
+ profile->mSupportedDevices.types());
module->mInputProfiles.add(profile);
return NO_ERROR;
@@ -3927,13 +4152,13 @@ status_t AudioPolicyManager::loadOutput(cnode *root, HwModule *module)
} else if (strcmp(node->name, CHANNELS_TAG) == 0) {
loadOutChannels((char *)node->value, profile);
} else if (strcmp(node->name, DEVICES_TAG) == 0) {
- profile->mSupportedDevices = parseDeviceNames((char *)node->value);
+ profile->mSupportedDevices.loadDevicesFromType(parseDeviceNames((char *)node->value));
} else if (strcmp(node->name, FLAGS_TAG) == 0) {
profile->mFlags = parseFlagNames((char *)node->value);
}
node = node->next;
}
- ALOGW_IF(profile->mSupportedDevices == AUDIO_DEVICE_NONE,
+ ALOGW_IF(profile->mSupportedDevices.isEmpty(),
"loadOutput() invalid supported devices");
ALOGW_IF(profile->mChannelMasks.size() == 0,
"loadOutput() invalid supported channel masks");
@@ -3941,13 +4166,13 @@ status_t AudioPolicyManager::loadOutput(cnode *root, HwModule *module)
"loadOutput() invalid supported sampling rates");
ALOGW_IF(profile->mFormats.size() == 0,
"loadOutput() invalid supported formats");
- if ((profile->mSupportedDevices != AUDIO_DEVICE_NONE) &&
+ if (!profile->mSupportedDevices.isEmpty() &&
(profile->mChannelMasks.size() != 0) &&
(profile->mSamplingRates.size() != 0) &&
(profile->mFormats.size() != 0)) {
- ALOGV("loadOutput() adding output mSupportedDevices %04x, mFlags %04x",
- profile->mSupportedDevices, profile->mFlags);
+ ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
+ profile->mSupportedDevices.types(), profile->mFlags);
module->mOutputProfiles.add(profile);
return NO_ERROR;
@@ -4026,20 +4251,22 @@ void AudioPolicyManager::loadGlobalConfig(cnode *root)
node = node->first_child;
while (node) {
if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
- mAttachedOutputDevices = parseDeviceNames((char *)node->value);
- ALOGW_IF(mAttachedOutputDevices == AUDIO_DEVICE_NONE,
- "loadGlobalConfig() no attached output devices");
- ALOGV("loadGlobalConfig() mAttachedOutputDevices %04x", mAttachedOutputDevices);
+ mAvailableOutputDevices.loadDevicesFromType(parseDeviceNames((char *)node->value));
+ ALOGV("loadGlobalConfig() Attached Output Devices %08x",
+ mAvailableOutputDevices.types());
} else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
- mDefaultOutputDevice = (audio_devices_t)stringToEnum(sDeviceNameToEnumTable,
+ audio_devices_t device = (audio_devices_t)stringToEnum(sDeviceNameToEnumTable,
ARRAY_SIZE(sDeviceNameToEnumTable),
(char *)node->value);
- ALOGW_IF(mDefaultOutputDevice == AUDIO_DEVICE_NONE,
- "loadGlobalConfig() default device not specified");
- ALOGV("loadGlobalConfig() mDefaultOutputDevice %04x", mDefaultOutputDevice);
+ if (device != AUDIO_DEVICE_NONE) {
+ mDefaultOutputDevice = new DeviceDescriptor(device);
+ } else {
+ ALOGW("loadGlobalConfig() default device not specified");
+ }
+ ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", mDefaultOutputDevice->mType);
} else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
- mAvailableInputDevices = parseDeviceNames((char *)node->value) & ~AUDIO_DEVICE_BIT_IN;
- ALOGV("loadGlobalConfig() mAvailableInputDevices %04x", mAvailableInputDevices);
+ mAvailableInputDevices.loadDevicesFromType(parseDeviceNames((char *)node->value));
+ ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types());
} else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
mSpeakerDrcEnabled = stringToBool((char *)node->value);
ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled);
@@ -4076,10 +4303,9 @@ void AudioPolicyManager::defaultAudioPolicyConfig(void)
{
HwModule *module;
IOProfile *profile;
-
- mDefaultOutputDevice = AUDIO_DEVICE_OUT_SPEAKER;
- mAttachedOutputDevices = AUDIO_DEVICE_OUT_SPEAKER;
- mAvailableInputDevices = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN;
+ sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
+ mAvailableOutputDevices.add(mDefaultOutputDevice);
+ mAvailableInputDevices.add(defaultInputDevice);
module = new HwModule("primary");
@@ -4087,7 +4313,7 @@ void AudioPolicyManager::defaultAudioPolicyConfig(void)
profile->mSamplingRates.add(44100);
profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
profile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO);
- profile->mSupportedDevices = AUDIO_DEVICE_OUT_SPEAKER;
+ profile->mSupportedDevices.add(mDefaultOutputDevice);
profile->mFlags = AUDIO_OUTPUT_FLAG_PRIMARY;
module->mOutputProfiles.add(profile);
@@ -4095,7 +4321,7 @@ void AudioPolicyManager::defaultAudioPolicyConfig(void)
profile->mSamplingRates.add(8000);
profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
profile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO);
- profile->mSupportedDevices = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ profile->mSupportedDevices.add(defaultInputDevice);
module->mInputProfiles.add(profile);
mHwModules.add(module);
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index e00d8ab..4c366bd 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -175,6 +175,47 @@ protected:
class IOProfile;
+ class DeviceDescriptor: public RefBase
+ {
+ public:
+ DeviceDescriptor(audio_devices_t type, String8 address,
+ audio_channel_mask_t channelMask) :
+ mType(type), mAddress(address),
+ mChannelMask(channelMask), mId(0) {}
+
+ DeviceDescriptor(audio_devices_t type) :
+ mType(type), mAddress(""),
+ mChannelMask(AUDIO_CHANNEL_NONE), mId(0) {}
+
+ status_t dump(int fd, int spaces) const;
+ static void dumpHeader(int fd, int spaces);
+
+ bool equals(const sp<DeviceDescriptor>& other) const;
+
+ audio_devices_t mType;
+ String8 mAddress;
+ audio_channel_mask_t mChannelMask;
+ uint32_t mId;
+ };
+
+ class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
+ {
+ public:
+ DeviceVector() : SortedVector(), mTypes(AUDIO_DEVICE_NONE) {}
+
+ ssize_t add(const sp<DeviceDescriptor>& item);
+ ssize_t remove(const sp<DeviceDescriptor>& item);
+ ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
+
+ audio_devices_t types() const { return mTypes; }
+
+ void loadDevicesFromType(audio_devices_t types);
+
+ private:
+ void refreshTypes();
+ audio_devices_t mTypes;
+ };
+
class HwModule {
public:
HwModule(const char *name);
@@ -213,8 +254,8 @@ protected:
Vector <uint32_t> mSamplingRates; // supported sampling rates
Vector <audio_channel_mask_t> mChannelMasks; // supported channel masks
Vector <audio_format_t> mFormats; // supported audio formats
- audio_devices_t mSupportedDevices; // supported devices (devices this output can be
- // routed to)
+ DeviceVector mSupportedDevices; // supported devices
+ // (devices this output can be routed to)
audio_output_flags_t mFlags; // attribute flags (e.g primary output,
// direct output...). For outputs only.
HwModule *mModule; // audio HW module exposing this I/O stream
@@ -411,7 +452,7 @@ protected:
status_t checkOutputsForDevice(audio_devices_t device,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& outputs,
- const String8 paramStr);
+ const String8 address);
// close an output and its companion duplicating output.
void closeOutput(audio_io_handle_t output);
@@ -496,6 +537,9 @@ protected:
static uint32_t stringToEnum(const struct StringToEnum *table,
size_t size,
const char *name);
+ static const char *enumToString(const struct StringToEnum *table,
+ size_t size,
+ uint32_t value);
static bool stringToBool(const char *value);
static audio_output_flags_t parseFlagNames(char *name);
static audio_devices_t parseDeviceNames(char *name);
@@ -520,18 +564,14 @@ protected:
// reset to mOutputs when updateDevicesAndOutputs() is called.
DefaultKeyedVector<audio_io_handle_t, AudioOutputDescriptor *> mPreviousOutputs;
DefaultKeyedVector<audio_io_handle_t, AudioInputDescriptor *> mInputs; // list of input descriptors
- audio_devices_t mAvailableOutputDevices; // bit field of all available output devices
- audio_devices_t mAvailableInputDevices; // bit field of all available input devices
+ DeviceVector mAvailableOutputDevices; // bit field of all available output devices
+ DeviceVector mAvailableInputDevices; // bit field of all available input devices
// without AUDIO_DEVICE_BIT_IN to allow direct bit
// field comparisons
int mPhoneState; // current phone state
audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT]; // current forced use configuration
StreamDescriptor mStreams[AUDIO_STREAM_CNT]; // stream descriptors for volume control
- String8 mA2dpDeviceAddress; // A2DP device MAC address
- String8 mScoDeviceAddress; // SCO device MAC address
- String8 mUsbCardAndDevice; // USB audio ALSA card and device numbers:
- // card=<card_number>;device=<><device_number>
bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected
audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
float mLastVoiceVolume; // last voice volume value sent to audio HAL
@@ -547,13 +587,12 @@ protected:
bool mHasA2dp; // true on platforms with support for bluetooth A2DP
bool mHasUsb; // true on platforms with support for USB audio
bool mHasRemoteSubmix; // true on platforms with support for remote presentation of a submix
- audio_devices_t mAttachedOutputDevices; // output devices always available on the platform
- audio_devices_t mDefaultOutputDevice; // output device selected by default at boot time
- // (must be in mAttachedOutputDevices)
+ sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
bool mSpeakerDrcEnabled;// true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path
// to boost soft sounds, used to adjust volume curves accordingly
Vector <HwModule *> mHwModules;
+ volatile int32_t mNextUniqueId;
#ifdef AUDIO_POLICY_TEST
Mutex mLock;
@@ -577,6 +616,9 @@ private:
// routing of notifications
void handleNotificationRoutingForStream(audio_stream_type_t stream);
static bool isVirtualInputDevice(audio_devices_t device);
+ uint32_t nextUniqueId();
+ // converts device address to string sent to audio HAL via setParameters
+ static String8 addressToParameter(audio_devices_t device, const String8 address);
};
};