From 817729095966c338615a8a791d2dbf774fc034ef Mon Sep 17 00:00:00 2001 From: jiabin Date: Mon, 2 Apr 2018 17:52:27 -0700 Subject: [PATCH] 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 --- media/libaudioclient/AudioSystem.cpp | 18 + media/libaudioclient/IAudioPolicyService.cpp | 100 +++- .../include/media/AudioSystem.h | 9 + .../include/media/IAudioPolicyService.h | 6 + services/audiopolicy/AudioPolicyInterface.h | 6 + .../audiopolicy/enginedefault/src/Engine.cpp | 3 +- .../managerdefault/AudioPolicyManager.cpp | 448 +++++++++++++++--- .../managerdefault/AudioPolicyManager.h | 12 + .../service/AudioPolicyInterfaceImpl.cpp | 23 + .../audiopolicy/service/AudioPolicyService.h | 6 + 10 files changed, 564 insertions(+), 67 deletions(-) diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index 39ee437044..c072901a40 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -1286,6 +1286,24 @@ status_t AudioSystem::getMicrophones(std::vector *microph return af->getMicrophones(microphones); } +status_t AudioSystem::getSurroundFormats(unsigned int *numSurroundFormats, + audio_format_t *surroundFormats, + bool *surroundFormatsEnabled, + bool reported) +{ + const sp& 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& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->setSurroundFormatEnabled(audioFormat, enabled); +} + // --------------------------------------------------------------------------- int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback( diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index 79b3e0f21d..dcd305bd95 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -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); } diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h index 0c4d6ee9a8..4c0f796f5e 100644 --- a/media/libaudioclient/include/media/AudioSystem.h +++ b/media/libaudioclient/include/media/AudioSystem.h @@ -340,6 +340,15 @@ public: static status_t getMicrophones(std::vector *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 diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h index 1114eeb785..c3876afc40 100644 --- a/media/libaudioclient/include/media/IAudioPolicyService.h +++ b/media/libaudioclient/include/media/IAudioPolicyService.h @@ -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; }; diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index 923c0914ac..4812b1fe7d 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -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); }; diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp index 83aec3bacf..23c020d796 100644 --- a/services/audiopolicy/enginedefault/src/Engine.cpp +++ b/services/audiopolicy/enginedefault/src/Engine.cpp @@ -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; } diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index e1467b704f..a141f49d3d 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -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 outputs; + bool reportedFormatFound = false; + status_t status; + sp 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 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 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) { diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index 2b68882215..62a14df293 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -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 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); diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 008d655e7a..35857cc29c 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -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 diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index d8dd797277..3e179c088d 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -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);