Add support for manually set surround formats.

To make surround sound setting more clear to users, we are changing
surround setting from ALWAYS to MANUAL. With MANUAL, users could enable
surround formats according to their need.

Bug: 67479735
Test: Try creating AudioTrack with enable/disable surround formats.
Change-Id: Ia6c0e1210ff6215f4b80a278a0aa90ca9543f262
gugelfrei
jiabin 6 years ago
parent 183eb5fb74
commit 8177290959

@ -1286,6 +1286,24 @@ status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfo> *microph
return af->getMicrophones(microphones);
}
status_t AudioSystem::getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->getSurroundFormats(
numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
}
status_t AudioSystem::setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setSurroundFormatEnabled(audioFormat, enabled);
}
// ---------------------------------------------------------------------------
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(

@ -80,7 +80,9 @@ enum {
SET_AUDIO_PORT_CALLBACK_ENABLED,
SET_MASTER_MONO,
GET_MASTER_MONO,
GET_STREAM_VOLUME_DB
GET_STREAM_VOLUME_DB,
GET_SURROUND_FORMATS,
SET_SURROUND_FORMAT_ENABLED
};
#define MAX_ITEMS_PER_LIST 1024
@ -829,6 +831,54 @@ public:
}
return reply.readFloat();
}
virtual status_t getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported)
{
if (numSurroundFormats == NULL || (*numSurroundFormats != 0 &&
(surroundFormats == NULL || surroundFormatsEnabled == NULL))) {
return BAD_VALUE;
}
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
unsigned int numSurroundFormatsReq = *numSurroundFormats;
data.writeUint32(numSurroundFormatsReq);
data.writeBool(reported);
status_t status = remote()->transact(GET_SURROUND_FORMATS, data, &reply);
if (status == NO_ERROR && (status = (status_t)reply.readInt32()) == NO_ERROR) {
*numSurroundFormats = reply.readUint32();
}
if (status == NO_ERROR) {
if (numSurroundFormatsReq > *numSurroundFormats) {
numSurroundFormatsReq = *numSurroundFormats;
}
if (numSurroundFormatsReq > 0) {
status = reply.read(surroundFormats,
numSurroundFormatsReq * sizeof(audio_format_t));
if (status != NO_ERROR) {
return status;
}
status = reply.read(surroundFormatsEnabled,
numSurroundFormatsReq * sizeof(bool));
}
}
return status;
}
virtual status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(audioFormat);
data.writeBool(enabled);
status_t status = remote()->transact(SET_SURROUND_FORMAT_ENABLED, data, &reply);
if (status != NO_ERROR) {
return status;
}
return reply.readInt32();
}
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@ -882,7 +932,9 @@ status_t BnAudioPolicyService::onTransact(
case REGISTER_POLICY_MIXES:
case SET_MASTER_MONO:
case START_AUDIO_SOURCE:
case STOP_AUDIO_SOURCE: {
case STOP_AUDIO_SOURCE:
case GET_SURROUND_FORMATS:
case SET_SURROUND_FORMAT_ENABLED: {
if (multiuser_get_app_id(IPCThreadState::self()->getCallingUid()) >= AID_APP_START) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@ -1488,6 +1540,50 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
}
case GET_SURROUND_FORMATS: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
unsigned int numSurroundFormatsReq = data.readUint32();
if (numSurroundFormatsReq > MAX_ITEMS_PER_LIST) {
numSurroundFormatsReq = MAX_ITEMS_PER_LIST;
}
bool reported = data.readBool();
unsigned int numSurroundFormats = numSurroundFormatsReq;
audio_format_t *surroundFormats = (audio_format_t *)calloc(
numSurroundFormats, sizeof(audio_format_t));
bool *surroundFormatsEnabled = (bool *)calloc(numSurroundFormats, sizeof(bool));
if (numSurroundFormatsReq > 0 &&
(surroundFormats == NULL || surroundFormatsEnabled == NULL)) {
free(surroundFormats);
free(surroundFormatsEnabled);
reply->writeInt32(NO_MEMORY);
return NO_ERROR;
}
status_t status = getSurroundFormats(
&numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->writeUint32(numSurroundFormats);
if (numSurroundFormatsReq > numSurroundFormats) {
numSurroundFormatsReq = numSurroundFormats;
}
reply->write(surroundFormats, numSurroundFormatsReq * sizeof(audio_format_t));
reply->write(surroundFormatsEnabled, numSurroundFormatsReq * sizeof(bool));
}
free(surroundFormats);
free(surroundFormatsEnabled);
return NO_ERROR;
}
case SET_SURROUND_FORMAT_ENABLED: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_format_t audioFormat = (audio_format_t) data.readInt32();
bool enabled = data.readBool();
status_t status = setSurroundFormatEnabled(audioFormat, enabled);
reply->writeInt32(status);
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}

@ -340,6 +340,15 @@ public:
static status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
// numSurroundFormats holds the maximum number of formats and bool value allowed in the array.
// When numSurroundFormats is 0, surroundFormats and surroundFormatsEnabled will not be
// populated. The actual number of surround formats should be returned at numSurroundFormats.
static status_t getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported);
static status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled);
// ----------------------------------------------------------------------------
class AudioPortCallback : public RefBase

@ -166,6 +166,12 @@ public:
virtual status_t getMasterMono(bool *mono) = 0;
virtual float getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device) = 0;
virtual status_t getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported) = 0;
virtual status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled) = 0;
};

@ -245,6 +245,12 @@ public:
virtual float getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device) = 0;
virtual status_t getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported) = 0;
virtual status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled) = 0;
virtual void setRecordSilenced(uid_t uid, bool silenced);
};

@ -148,7 +148,8 @@ status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced
case AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:
if (config != AUDIO_POLICY_FORCE_NONE &&
config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER &&
config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS &&
config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
ALOGW("setForceUse() invalid config %d for ENCODED_SURROUND", config);
return BAD_VALUE;
}

@ -60,6 +60,26 @@ namespace android {
// media / notification / system volume.
constexpr float IN_CALL_EARPIECE_HEADROOM_DB = 3.f;
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
// Array of all surround formats.
static const audio_format_t SURROUND_FORMATS[] = {
AUDIO_FORMAT_AC3,
AUDIO_FORMAT_E_AC3,
AUDIO_FORMAT_DTS,
AUDIO_FORMAT_DTS_HD,
AUDIO_FORMAT_AAC_LC,
AUDIO_FORMAT_DOLBY_TRUEHD,
AUDIO_FORMAT_E_AC3_JOC,
};
// Array of all AAC formats. When AAC is enabled by users, all AAC formats should be enabled.
static const audio_format_t AAC_FORMATS[] = {
AUDIO_FORMAT_AAC_LC,
AUDIO_FORMAT_AAC_HE_V1,
AUDIO_FORMAT_AAC_HE_V2,
AUDIO_FORMAT_AAC_ELD,
AUDIO_FORMAT_AAC_XHE,
};
// ----------------------------------------------------------------------------
// AudioPolicyInterface implementation
// ----------------------------------------------------------------------------
@ -3461,6 +3481,275 @@ float AudioPolicyManager::getStreamVolumeDB(
return computeVolume(stream, index, device);
}
status_t AudioPolicyManager::getSupportedFormats(audio_io_handle_t ioHandle,
FormatVector& formats) {
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
return BAD_VALUE;
}
String8 reply;
reply = mpClientInterface->getParameters(
ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
ALOGV("%s: supported formats %s", __FUNCTION__, reply.string());
AudioParameter repliedParameters(reply);
if (repliedParameters.get(
String8(AudioParameter::keyStreamSupportedFormats), reply) != NO_ERROR) {
ALOGE("%s: failed to retrieve format, bailing out", __FUNCTION__);
return BAD_VALUE;
}
for (auto format : formatsFromString(reply.string())) {
// Only AUDIO_FORMAT_AAC_LC will be used in Settings UI for all AAC formats.
for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
if (format == AAC_FORMATS[i]) {
format = AUDIO_FORMAT_AAC_LC;
break;
}
}
bool exist = false;
for (size_t i = 0; i < formats.size(); i++) {
if (format == formats[i]) {
exist = true;
break;
}
}
bool isSurroundFormat = false;
for (size_t i = 0; i < ARRAY_SIZE(SURROUND_FORMATS); i++) {
if (SURROUND_FORMATS[i] == format) {
isSurroundFormat = true;
break;
}
}
if (!exist && isSurroundFormat) {
formats.add(format);
}
}
return NO_ERROR;
}
status_t AudioPolicyManager::getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported)
{
if (numSurroundFormats == NULL || (*numSurroundFormats != 0 &&
(surroundFormats == NULL || surroundFormatsEnabled == NULL))) {
return BAD_VALUE;
}
ALOGV("getSurroundFormats() numSurroundFormats %d surroundFormats %p surroundFormatsEnabled %p",
*numSurroundFormats, surroundFormats, surroundFormatsEnabled);
// Only return value if there is HDMI output.
if ((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_HDMI) == 0) {
return INVALID_OPERATION;
}
size_t formatsWritten = 0;
size_t formatsMax = *numSurroundFormats;
*numSurroundFormats = 0;
FormatVector formats;
if (reported) {
// Only get surround formats which are reported by device.
// First list already open outputs that can be routed to this device
audio_devices_t device = AUDIO_DEVICE_OUT_HDMI;
SortedVector<audio_io_handle_t> outputs;
bool reportedFormatFound = false;
status_t status;
sp<SwAudioOutputDescriptor> desc;
for (size_t i = 0; i < mOutputs.size(); i++) {
desc = mOutputs.valueAt(i);
if (!desc->isDuplicated() && (desc->supportedDevices() & device)) {
outputs.add(mOutputs.keyAt(i));
}
}
// Open an output to query dynamic parameters.
DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_HDMI);
for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
String8 address = hdmiOutputDevices[i]->mAddress;
for (const auto& hwModule : mHwModules) {
for (size_t i = 0; i < hwModule->getOutputProfiles().size(); i++) {
sp<IOProfile> profile = hwModule->getOutputProfiles()[i];
if (profile->supportDevice(AUDIO_DEVICE_OUT_HDMI) &&
profile->supportDeviceAddress(address)) {
size_t j;
for (j = 0; j < outputs.size(); j++) {
desc = mOutputs.valueFor(outputs.itemAt(j));
if (!desc->isDuplicated() && desc->mProfile == profile) {
break;
}
}
if (j != outputs.size()) {
status = getSupportedFormats(outputs.itemAt(j), formats);
reportedFormatFound |= (status == NO_ERROR);
continue;
}
if (!profile->canOpenNewIo()) {
ALOGW("Max Output number %u already opened for this profile %s",
profile->maxOpenCount, profile->getTagName().c_str());
continue;
}
ALOGV("opening output for device %08x with params %s profile %p name %s",
device, address.string(), profile.get(), profile->getName().string());
desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status = desc->open(nullptr, device, address,
AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE,
&output);
if (status == NO_ERROR) {
status = getSupportedFormats(output, formats);
reportedFormatFound |= (status == NO_ERROR);
desc->close();
output = AUDIO_IO_HANDLE_NONE;
}
}
}
}
}
if (!reportedFormatFound) {
return UNKNOWN_ERROR;
}
} else {
for (size_t i = 0; i < ARRAY_SIZE(SURROUND_FORMATS); i++) {
formats.add(SURROUND_FORMATS[i]);
}
}
for (size_t i = 0; i < formats.size(); i++) {
if (formatsWritten < formatsMax) {
surroundFormats[formatsWritten] = formats[i];
bool formatEnabled = false;
if (formats[i] == AUDIO_FORMAT_AAC_LC) {
for (size_t j = 0; j < ARRAY_SIZE(AAC_FORMATS); j++) {
formatEnabled =
mSurroundFormats.find(AAC_FORMATS[i]) != mSurroundFormats.end();
break;
}
} else {
formatEnabled = mSurroundFormats.find(formats[i]) != mSurroundFormats.end();
}
surroundFormatsEnabled[formatsWritten++] = formatEnabled;
}
(*numSurroundFormats)++;
}
return NO_ERROR;
}
status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled)
{
// Check if audio format is a surround formats.
bool isSurroundFormat = false;
for (size_t i = 0; i < ARRAY_SIZE(SURROUND_FORMATS); i++) {
if (audioFormat == SURROUND_FORMATS[i]) {
isSurroundFormat = true;
break;
}
}
if (!isSurroundFormat) {
return BAD_VALUE;
}
// Should only be called when MANUAL.
audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
if (forceUse != AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
return INVALID_OPERATION;
}
if ((mSurroundFormats.find(audioFormat) != mSurroundFormats.end() && enabled)
|| (mSurroundFormats.find(audioFormat) == mSurroundFormats.end() && !enabled)) {
return NO_ERROR;
}
// The operation is valid only when there is HDMI output available.
if ((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_HDMI) == 0) {
return INVALID_OPERATION;
}
if (enabled) {
if (audioFormat == AUDIO_FORMAT_AAC_LC) {
for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
mSurroundFormats.insert(AAC_FORMATS[i]);
}
} else {
mSurroundFormats.insert(audioFormat);
}
} else {
if (audioFormat == AUDIO_FORMAT_AAC_LC) {
for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
mSurroundFormats.erase(AAC_FORMATS[i]);
}
} else {
mSurroundFormats.erase(audioFormat);
}
}
sp<SwAudioOutputDescriptor> outputDesc;
bool profileUpdated = false;
DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_HDMI);
for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
String8 address = hdmiOutputDevices[i]->mAddress;
String8 name = hdmiOutputDevices[i]->getName();
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
address.c_str(),
name.c_str());
if (status != NO_ERROR) {
continue;
}
status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address.c_str(),
name.c_str());
profileUpdated |= (status == NO_ERROR);
}
DeviceVector hdmiInputDevices = mAvailableInputDevices.getDevicesFromType(
AUDIO_DEVICE_IN_HDMI);
for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
String8 address = hdmiInputDevices[i]->mAddress;
String8 name = hdmiInputDevices[i]->getName();
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
address.c_str(),
name.c_str());
if (status != NO_ERROR) {
continue;
}
status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address.c_str(),
name.c_str());
profileUpdated |= (status == NO_ERROR);
}
// Undo the surround formats change due to no audio profiles updated.
if (!profileUpdated) {
if (enabled) {
if (audioFormat == AUDIO_FORMAT_AAC_LC) {
for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
mSurroundFormats.erase(AAC_FORMATS[i]);
}
} else {
mSurroundFormats.erase(audioFormat);
}
} else {
if (audioFormat == AUDIO_FORMAT_AAC_LC) {
for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
mSurroundFormats.insert(AAC_FORMATS[i]);
}
} else {
mSurroundFormats.insert(audioFormat);
}
}
}
return profileUpdated ? NO_ERROR : INVALID_OPERATION;
}
void AudioPolicyManager::setRecordSilenced(uid_t uid, bool silenced)
{
ALOGV("AudioPolicyManager:setRecordSilenced(uid:%d, silenced:%d)", uid, silenced);
@ -3834,6 +4123,7 @@ AudioPolicyManager::~AudioPolicyManager()
mInputs.clear();
mHwModules.clear();
mHwModulesAll.clear();
mSurroundFormats.clear();
}
status_t AudioPolicyManager::initCheck()
@ -5581,81 +5871,110 @@ void AudioPolicyManager::filterSurroundFormats(FormatVector *formatsPtr) {
AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
ALOGD("%s: forced use = %d", __FUNCTION__, forceUse);
// Analyze original support for various formats.
bool supportsAC3 = false;
bool supportsOtherSurround = false;
bool supportsIEC61937 = false;
for (ssize_t formatIndex = 0; formatIndex < (ssize_t)formats.size(); formatIndex++) {
audio_format_t format = formats[formatIndex];
switch (format) {
case AUDIO_FORMAT_AC3:
supportsAC3 = true;
break;
case AUDIO_FORMAT_E_AC3:
case AUDIO_FORMAT_DTS:
case AUDIO_FORMAT_DTS_HD:
// If ALWAYS, remove all other surround formats here since we will add them later.
if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
formats.removeAt(formatIndex);
formatIndex--;
// If MANUAL, keep the supported surround sound formats as current enabled ones.
if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
formats.clear();
for (auto it = mSurroundFormats.begin(); it != mSurroundFormats.end(); it++) {
formats.add(*it);
}
// Always enable IEC61937 when in MANUAL mode.
formats.add(AUDIO_FORMAT_IEC61937);
} else { // NEVER, AUTO or ALWAYS
// Analyze original support for various formats.
bool supportsAC3 = false;
bool supportsOtherSurround = false;
bool supportsIEC61937 = false;
mSurroundFormats.clear();
for (ssize_t formatIndex = 0; formatIndex < (ssize_t)formats.size(); formatIndex++) {
audio_format_t format = formats[formatIndex];
switch (format) {
case AUDIO_FORMAT_AC3:
supportsAC3 = true;
break;
case AUDIO_FORMAT_E_AC3:
case AUDIO_FORMAT_DTS:
case AUDIO_FORMAT_DTS_HD:
// If ALWAYS, remove all other surround formats here
// since we will add them later.
if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
formats.removeAt(formatIndex);
formatIndex--;
}
supportsOtherSurround = true;
break;
case AUDIO_FORMAT_IEC61937:
supportsIEC61937 = true;
break;
default:
break;
}
}
// Modify formats based on surround preferences.
// If NEVER, remove support for surround formats.
if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) {
if (supportsAC3 || supportsOtherSurround || supportsIEC61937) {
// Remove surround sound related formats.
for (size_t formatIndex = 0; formatIndex < formats.size(); ) {
audio_format_t format = formats[formatIndex];
switch(format) {
case AUDIO_FORMAT_AC3:
case AUDIO_FORMAT_E_AC3:
case AUDIO_FORMAT_DTS:
case AUDIO_FORMAT_DTS_HD:
case AUDIO_FORMAT_IEC61937:
formats.removeAt(formatIndex);
break;
default:
formatIndex++; // keep it
break;
}
}
supportsAC3 = false;
supportsOtherSurround = false;
supportsIEC61937 = false;
}
} else { // AUTO or ALWAYS
// Most TVs support AC3 even if they do not report it in the EDID.
if ((alwaysForceAC3 || (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS))
&& !supportsAC3) {
formats.add(AUDIO_FORMAT_AC3);
supportsAC3 = true;
}
// If ALWAYS, add support for raw surround formats if all are missing.
// This assumes that if any of these formats are reported by the HAL
// then the report is valid and should not be modified.
if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
formats.add(AUDIO_FORMAT_E_AC3);
formats.add(AUDIO_FORMAT_DTS);
formats.add(AUDIO_FORMAT_DTS_HD);
supportsOtherSurround = true;
break;
case AUDIO_FORMAT_IEC61937:
}
// Add support for IEC61937 if any raw surround supported.
// The HAL could do this but add it here, just in case.
if ((supportsAC3 || supportsOtherSurround) && !supportsIEC61937) {
formats.add(AUDIO_FORMAT_IEC61937);
supportsIEC61937 = true;
break;
default:
break;
}
}
}
// Modify formats based on surround preferences.
// If NEVER, remove support for surround formats.
if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) {
if (supportsAC3 || supportsOtherSurround || supportsIEC61937) {
// Remove surround sound related formats.
for (size_t formatIndex = 0; formatIndex < formats.size(); ) {
// Add reported surround sound formats to enabled surround formats.
for (size_t formatIndex = 0; formatIndex < formats.size(); formatIndex++) {
audio_format_t format = formats[formatIndex];
switch(format) {
case AUDIO_FORMAT_AC3:
case AUDIO_FORMAT_E_AC3:
case AUDIO_FORMAT_DTS:
case AUDIO_FORMAT_DTS_HD:
case AUDIO_FORMAT_IEC61937:
formats.removeAt(formatIndex);
break;
case AUDIO_FORMAT_AAC_LC:
case AUDIO_FORMAT_DOLBY_TRUEHD:
case AUDIO_FORMAT_E_AC3_JOC:
mSurroundFormats.insert(format);
default:
formatIndex++; // keep it
break;
}
}
supportsAC3 = false;
supportsOtherSurround = false;
supportsIEC61937 = false;
}
} else { // AUTO or ALWAYS
// Most TVs support AC3 even if they do not report it in the EDID.
if ((alwaysForceAC3 || (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS))
&& !supportsAC3) {
formats.add(AUDIO_FORMAT_AC3);
supportsAC3 = true;
}
// If ALWAYS, add support for raw surround formats if all are missing.
// This assumes that if any of these formats are reported by the HAL
// then the report is valid and should not be modified.
if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
formats.add(AUDIO_FORMAT_E_AC3);
formats.add(AUDIO_FORMAT_DTS);
formats.add(AUDIO_FORMAT_DTS_HD);
supportsOtherSurround = true;
}
// Add support for IEC61937 if any raw surround supported.
// The HAL could do this but add it here, just in case.
if ((supportsAC3 || supportsOtherSurround) && !supportsIEC61937) {
formats.add(AUDIO_FORMAT_IEC61937);
supportsIEC61937 = true;
}
}
}
@ -5677,8 +5996,9 @@ void AudioPolicyManager::filterSurroundChannelMasks(ChannelsVector *channelMasks
maskIndex++;
}
}
// If ALWAYS, then make sure we at least support 5.1
} else if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
// If ALWAYS or MANUAL, then make sure we at least support 5.1
} else if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS
|| forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
bool supports5dot1 = false;
// Are there any channel masks that can be considered "surround"?
for (audio_channel_mask_t channelMask : channelMasks) {
@ -5705,7 +6025,7 @@ void AudioPolicyManager::updateAudioProfiles(audio_devices_t device,
if (profiles.hasDynamicFormat()) {
reply = mpClientInterface->getParameters(
ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
ALOGV("%s: supported formats %s", __FUNCTION__, reply.string());
ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.string());
AudioParameter repliedParameters(reply);
if (repliedParameters.get(
String8(AudioParameter::keyStreamSupportedFormats), reply) != NO_ERROR) {

@ -18,6 +18,7 @@
#include <atomic>
#include <memory>
#include <unordered_set>
#include <stdint.h>
#include <sys/types.h>
@ -233,6 +234,12 @@ public:
virtual float getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device);
virtual status_t getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported);
virtual status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled);
// return the strategy corresponding to a given stream type
routing_strategy getStrategy(audio_stream_type_t stream) const;
@ -592,11 +599,16 @@ protected:
// Audio Policy Engine Interface.
AudioPolicyManagerInterface *mEngine;
// Surround formats that are enabled.
std::unordered_set<audio_format_t> mSurroundFormats;
private:
// Add or remove AC3 DTS encodings based on user preferences.
void filterSurroundFormats(FormatVector *formatsPtr);
void filterSurroundChannelMasks(ChannelsVector *channelMasksPtr);
status_t getSupportedFormats(audio_io_handle_t ioHandle, FormatVector& formats);
// If any, resolve any "dynamic" fields of an Audio Profiles collection
void updateAudioProfiles(audio_devices_t device, audio_io_handle_t ioHandle,
AudioProfileVector &profiles);

@ -977,5 +977,28 @@ float AudioPolicyService::getStreamVolumeDB(
return mAudioPolicyManager->getStreamVolumeDB(stream, index, device);
}
status_t AudioPolicyService::getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
return mAudioPolicyManager->getSurroundFormats(numSurroundFormats, surroundFormats,
surroundFormatsEnabled, reported);
}
status_t AudioPolicyService::setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
return mAudioPolicyManager->setSurroundFormatEnabled(audioFormat, enabled);
}
} // namespace android

@ -203,6 +203,12 @@ public:
virtual float getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device);
virtual status_t getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
bool reported);
virtual status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled);
status_t doStopOutput(audio_io_handle_t output,
audio_stream_type_t stream,
audio_session_t session);

Loading…
Cancel
Save