From 000c3e44f3c449de255974965ca31b8ab7d3dc1a Mon Sep 17 00:00:00 2001 From: Ytai Ben-Tsvi Date: Thu, 9 Jan 2020 15:26:40 -0800 Subject: [PATCH] Support multiple error callbacks Move from a single callback model to allow multiple registrations. Created a separate mutex to guard the callback in order to simplify the process of invoking the callbacks safely without holding the main lock. Change-Id: Id09aedda785e99b31c70cba1681a2ee392e9b06c --- media/libaudioclient/AudioSystem.cpp | 33 ++++++++++++------- .../include/media/AudioSystem.h | 20 +++++++++-- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index 941cf54d8d..e0ca07edab 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 c4b528e959..201acca401 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); @@ -560,15 +570,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;