diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index 074209158f..ec22a54340 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -36,10 +36,11 @@ namespace android { // client singleton for AudioFlinger binder interface Mutex AudioSystem::gLock; +Mutex AudioSystem::gLockErrorCallbacks; Mutex AudioSystem::gLockAPS; sp AudioSystem::gAudioFlinger; sp AudioSystem::gAudioFlingerClient; -audio_error_callback AudioSystem::gAudioErrorCallback = NULL; +std::set AudioSystem::gAudioErrorCallbacks; dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL; record_config_callback AudioSystem::gRecordConfigCallback = NULL; @@ -63,9 +64,7 @@ const sp AudioSystem::get_audio_flinger() if (gAudioFlingerClient == NULL) { gAudioFlingerClient = new AudioFlingerClient(); } else { - if (gAudioErrorCallback) { - gAudioErrorCallback(NO_ERROR); - } + reportError(NO_ERROR); } binder->linkToDeath(gAudioFlingerClient); gAudioFlinger = interface_cast(binder); @@ -500,19 +499,16 @@ void AudioSystem::AudioFlingerClient::clearIoCache() void AudioSystem::AudioFlingerClient::binderDied(const wp& who __unused) { - audio_error_callback cb = NULL; { Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioFlinger.clear(); - cb = gAudioErrorCallback; } // clear output handles and stream to output map caches clearIoCache(); - if (cb) { - cb(DEAD_OBJECT); - } + reportError(DEAD_OBJECT); + ALOGW("AudioFlinger server died!"); } @@ -717,10 +713,23 @@ status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( return NO_ERROR; } -/* static */ void AudioSystem::setErrorCallback(audio_error_callback cb) +/* static */ uintptr_t AudioSystem::addErrorCallback(audio_error_callback cb) { - Mutex::Autolock _l(gLock); - gAudioErrorCallback = cb; + Mutex::Autolock _l(gLockErrorCallbacks); + gAudioErrorCallbacks.insert(cb); + return reinterpret_cast(cb); +} + +/* static */ void AudioSystem::removeErrorCallback(uintptr_t cb) { + Mutex::Autolock _l(gLockErrorCallbacks); + gAudioErrorCallbacks.erase(reinterpret_cast(cb)); +} + +/* static */ void AudioSystem::reportError(status_t err) { + Mutex::Autolock _l(gLockErrorCallbacks); + for (auto callback : gAudioErrorCallbacks) { + callback(err); + } } /*static*/ void AudioSystem::setDynPolicyCallback(dynamic_policy_callback cb) diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h index ae8b59cb72..8002289b2a 100644 --- a/media/libaudioclient/include/media/AudioSystem.h +++ b/media/libaudioclient/include/media/AudioSystem.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -107,7 +108,16 @@ public: static status_t setParameters(const String8& keyValuePairs); static String8 getParameters(const String8& keys); - static void setErrorCallback(audio_error_callback cb); + // Registers an error callback. When this callback is invoked, it means all + // state implied by this interface has been reset. + // Returns a token that can be used for un-registering. + // Might block while callbacks are being invoked. + static uintptr_t addErrorCallback(audio_error_callback cb); + + // Un-registers a callback previously added with addErrorCallback. + // Might block while callbacks are being invoked. + static void removeErrorCallback(uintptr_t cb); + static void setDynPolicyCallback(dynamic_policy_callback cb); static void setRecordConfigCallback(record_config_callback); @@ -562,15 +572,19 @@ private: static const sp getAudioFlingerClient(); static sp getIoDescriptor(audio_io_handle_t ioHandle); + // Invokes all registered error callbacks with the given error code. + static void reportError(status_t err); + static sp gAudioFlingerClient; static sp gAudioPolicyServiceClient; friend class AudioFlingerClient; friend class AudioPolicyServiceClient; - static Mutex gLock; // protects gAudioFlinger and gAudioErrorCallback, + static Mutex gLock; // protects gAudioFlinger + static Mutex gLockErrorCallbacks; // protects gAudioErrorCallbacks static Mutex gLockAPS; // protects gAudioPolicyService and gAudioPolicyServiceClient static sp gAudioFlinger; - static audio_error_callback gAudioErrorCallback; + static std::set gAudioErrorCallbacks; static dynamic_policy_callback gDynPolicyCallback; static record_config_callback gRecordConfigCallback;