@ -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 ) {