@ -522,8 +522,9 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
if ( ioDesc = = 0 | | ioDesc - > mIoHandle = = AUDIO_IO_HANDLE_NONE ) return ;
audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE ;
Vector < wp < AudioDeviceCallback > > callbacks ;
AudioDeviceCallbacks callbacks ;
bool deviceValidOrChanged = false ;
Mutex : : Autolock _l ( mCallbacksLock ) ;
{
Mutex : : Autolock _l ( mLock ) ;
@ -546,6 +547,13 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
ssize_t ioIndex = mAudioDeviceCallbacks . indexOfKey ( ioDesc - > mIoHandle ) ;
if ( ioIndex > = 0 ) {
callbacks = mAudioDeviceCallbacks . valueAt ( ioIndex ) ;
deviceValidOrChanged = true ;
}
}
if ( event = = AUDIO_OUTPUT_REGISTERED | | event = = AUDIO_INPUT_REGISTERED ) {
ssize_t ioIndex = mAudioDeviceCallbacks . indexOfKey ( ioDesc - > mIoHandle ) ;
if ( ( ioIndex > = 0 ) & & ! mAudioDeviceCallbacks . valueAt ( ioIndex ) . notifiedOnce ( ) ) {
callbacks = mAudioDeviceCallbacks . valueAt ( ioIndex ) ;
}
}
}
@ -584,6 +592,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
mIoDescriptors . replaceValueFor ( ioDesc - > mIoHandle , ioDesc ) ;
if ( deviceId ! = ioDesc - > getDeviceId ( ) ) {
deviceValidOrChanged = true ;
deviceId = ioDesc - > getDeviceId ( ) ;
ssize_t ioIndex = mAudioDeviceCallbacks . indexOfKey ( ioDesc - > mIoHandle ) ;
if ( ioIndex > = 0 ) {
@ -600,22 +609,28 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
} break ;
}
}
bool callbackRemoved = false ;
// callbacks.size() != 0 => ioDesc->mIoHandle and deviceId are valid
for ( size_t i = 0 ; i < callbacks . size ( ) ; ) {
sp < AudioDeviceCallback > callback = callbacks [ i ] . promote ( ) ;
if ( callback . get ( ) ! = nullptr ) {
callback - > onAudioDeviceUpdate ( ioDesc - > mIoHandle , deviceId ) ;
i + + ;
} else {
callbacks . removeAt ( i ) ;
callbackRemoved = true ;
if ( callbacks . size ( ) ! = 0 ) {
for ( size_t i = 0 ; i < callbacks . size ( ) ; ) {
sp < AudioDeviceCallback > callback = callbacks [ i ] . promote ( ) ;
if ( callback . get ( ) ! = nullptr ) {
// Call the callback only if the device actually changed, the input or output was
// opened or closed or the client was newly registered and the callback was never
// called
if ( ! callback - > notifiedOnce ( ) | | deviceValidOrChanged ) {
// Must be called without mLock held. May lead to dead lock if calling for
// example getRoutedDevice that updates the device and tries to acquire mLock.
callback - > onAudioDeviceUpdate ( ioDesc - > mIoHandle , deviceId ) ;
callback - > setNotifiedOnce ( ) ;
}
i + + ;
} else {
callbacks . removeAt ( i ) ;
}
}
}
// clean up callback list while we are here if some clients have disappeared without
// unregistering their callback
if ( callbackRemoved ) {
Mutex : : Autolock _l ( mLock ) ;
callbacks . setNotifiedOnce ( ) ;
// clean up callback list while we are here if some clients have disappeared without
// unregistering their callback, or if cb was served for the first time since registered
mAudioDeviceCallbacks . replaceValueFor ( ioDesc - > mIoHandle , callbacks ) ;
}
}
@ -671,8 +686,8 @@ sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_
status_t AudioSystem : : AudioFlingerClient : : addAudioDeviceCallback (
const wp < AudioDeviceCallback > & callback , audio_io_handle_t audioIo )
{
Mutex : : Autolock _l ( m Lock) ;
Vector < wp < AudioDeviceCallback > > callbacks ;
Mutex : : Autolock _l ( m Callbacks Lock) ;
AudioDeviceCallbacks callbacks ;
ssize_t ioIndex = mAudioDeviceCallbacks . indexOfKey ( audioIo ) ;
if ( ioIndex > = 0 ) {
callbacks = mAudioDeviceCallbacks . valueAt ( ioIndex ) ;
@ -684,7 +699,7 @@ status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
}
}
callbacks . add ( callback ) ;
callbacks . resetNotifiedOnce ( ) ;
mAudioDeviceCallbacks . replaceValueFor ( audioIo , callbacks ) ;
return NO_ERROR ;
}
@ -692,12 +707,12 @@ status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
status_t AudioSystem : : AudioFlingerClient : : removeAudioDeviceCallback (
const wp < AudioDeviceCallback > & callback , audio_io_handle_t audioIo )
{
Mutex : : Autolock _l ( m Lock) ;
Mutex : : Autolock _l ( m Callbacks Lock) ;
ssize_t ioIndex = mAudioDeviceCallbacks . indexOfKey ( audioIo ) ;
if ( ioIndex < 0 ) {
return INVALID_OPERATION ;
}
Vector < wp < AudioDeviceCallback > > callbacks = mAudioDeviceCallbacks . valueAt ( ioIndex ) ;
AudioDeviceCallbacks callbacks = mAudioDeviceCallbacks . valueAt ( ioIndex ) ;
size_t cbIndex ;
for ( cbIndex = 0 ; cbIndex < callbacks . size ( ) ; cbIndex + + ) {