Loading media/libaudioclient/AudioSystem.cpp +143 −83 Original line number Diff line number Diff line Loading @@ -66,10 +66,6 @@ using media::audio::common::AudioUsage; using media::audio::common::Int; std::mutex AudioSystem::gMutex; sp<IAudioFlinger> AudioSystem::gAudioFlinger; sp<IBinder> AudioSystem::gAudioFlingerBinder; sp<IAudioFlinger> AudioSystem::gLocalAudioFlinger; sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient; dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL; record_config_callback AudioSystem::gRecordConfigCallback = NULL; routing_callback AudioSystem::gRoutingCallback = NULL; Loading @@ -89,90 +85,167 @@ sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient // from the system server. // This allows specific isolated processes to access the audio system. Currently used only for the // HotwordDetectionService. void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) { if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) { ALOGE("setAudioFlingerBinder: received a binder of type %s", String8(audioFlinger->getInterfaceDescriptor()).c_str()); return; } std::lock_guard _l(gMutex); if (gAudioFlinger != nullptr) { ALOGW("setAudioFlingerBinder: ignoring; AudioFlinger connection already established."); return; } gAudioFlingerBinder = audioFlinger; } status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) { std::lock_guard _l(gMutex); if (gAudioFlinger != nullptr) return INVALID_OPERATION; gLocalAudioFlinger = af; return OK; } template <typename ServiceInterface, typename Client, typename AidlInterface, typename ServiceTraits> class ServiceHandler { public: sp<ServiceInterface> getService(bool canStartThreadPool = true) EXCLUDES(mMutex) NO_THREAD_SAFETY_ANALYSIS { // std::unique_ptr sp<ServiceInterface> service; sp<Client> client; // establish binder interface to AudioFlinger service const sp<IAudioFlinger> AudioSystem::getAudioFlingerImpl(bool canStartThreadPool = true) { sp<IAudioFlinger> af; sp<AudioFlingerClient> afc; bool reportNoError = false; { std::lock_guard _l(gMutex); if (gAudioFlinger != nullptr) { return gAudioFlinger; std::lock_guard _l(mMutex); if (mService != nullptr) { return mService; } } if (gAudioFlingerClient == nullptr) { gAudioFlingerClient = sp<AudioFlingerClient>::make(); std::unique_lock ul_only1thread(mSingleGetter); std::unique_lock ul(mMutex); if (mService != nullptr) { return mService; } if (mClient == nullptr) { mClient = sp<Client>::make(); } else { reportNoError = true; } while (true) { mService = mLocalService; if (mService != nullptr) break; if (gLocalAudioFlinger != nullptr) { gAudioFlinger = gLocalAudioFlinger; } else { sp<IBinder> binder; if (gAudioFlingerBinder != nullptr) { binder = gAudioFlingerBinder; } else { sp<IBinder> binder = mBinder; if (binder == nullptr) { sp <IServiceManager> sm = defaultServiceManager(); binder = sm->waitForService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME)); binder = sm->checkService(String16(ServiceTraits::SERVICE_NAME)); if (binder == nullptr) { return nullptr; ALOGD("%s: waiting for %s", __func__, ServiceTraits::SERVICE_NAME); // if the condition variable is present, setLocalService() and // setBinder() is allowed to use it to notify us. if (mCvGetter == nullptr) { mCvGetter = std::make_shared<std::condition_variable>(); } mCvGetter->wait_for(ul, std::chrono::seconds(1)); continue; } } binder->linkToDeath(gAudioFlingerClient); const auto afs = interface_cast<media::IAudioFlingerService>(binder); LOG_ALWAYS_FATAL_IF(afs == nullptr); gAudioFlinger = sp<AudioFlingerClientAdapter>::make(afs); binder->linkToDeath(mClient); auto aidlInterface = interface_cast<AidlInterface>(binder); LOG_ALWAYS_FATAL_IF(aidlInterface == nullptr); if constexpr (std::is_same_v<ServiceInterface, AidlInterface>) { mService = std::move(aidlInterface); } else /* constexpr */ { mService = ServiceTraits::createServiceAdapter(aidlInterface); } afc = gAudioFlingerClient; af = gAudioFlinger; // Make sure callbacks can be received by gAudioFlingerClient break; } if (mCvGetter) mCvGetter.reset(); // remove condition variable. client = mClient; service = mService; // Make sure callbacks can be received by the client if (canStartThreadPool) { ProcessState::self()->startThreadPool(); } ul.unlock(); ul_only1thread.unlock(); ServiceTraits::onServiceCreate(service, client); if (reportNoError) AudioSystem::reportError(NO_ERROR); return service; } status_t setLocalService(const sp<ServiceInterface>& service) EXCLUDES(mMutex) { std::lock_guard _l(mMutex); // we allow clearing once set, but not a double non-null set. if (mService != nullptr && service != nullptr) return INVALID_OPERATION; mLocalService = service; if (mCvGetter) mCvGetter->notify_one(); return OK; } sp<Client> getClient() EXCLUDES(mMutex) { const auto service = getService(); if (service == nullptr) return nullptr; std::lock_guard _l(mMutex); return mClient; } void setBinder(const sp<IBinder>& binder) EXCLUDES(mMutex) { std::lock_guard _l(mMutex); if (mService != nullptr) { ALOGW("%s: ignoring; %s connection already established.", __func__, ServiceTraits::SERVICE_NAME); return; } mBinder = binder; if (mCvGetter) mCvGetter->notify_one(); } void clearService() EXCLUDES(mMutex) { std::lock_guard _l(mMutex); mService.clear(); if (mClient) ServiceTraits::onClearService(mClient); } private: std::mutex mSingleGetter; std::mutex mMutex; std::shared_ptr<std::condition_variable> mCvGetter GUARDED_BY(mMutex); sp<IBinder> mBinder GUARDED_BY(mMutex); sp<ServiceInterface> mLocalService GUARDED_BY(mMutex); sp<ServiceInterface> mService GUARDED_BY(mMutex); sp<Client> mClient GUARDED_BY(mMutex); }; struct AudioFlingerTraits { static void onServiceCreate( const sp<IAudioFlinger>& af, const sp<AudioSystem::AudioFlingerClient>& afc) { const int64_t token = IPCThreadState::self()->clearCallingIdentity(); af->registerClient(afc); IPCThreadState::self()->restoreCallingIdentity(token); if (reportNoError) reportError(NO_ERROR); return af; } static sp<IAudioFlinger> createServiceAdapter( const sp<media::IAudioFlingerService>& aidlInterface) { return sp<AudioFlingerClientAdapter>::make(aidlInterface); } static void onClearService(const sp<AudioSystem::AudioFlingerClient>& afc) { afc->clearIoCache(); } static constexpr const char* SERVICE_NAME = IAudioFlinger::DEFAULT_SERVICE_NAME; }; [[clang::no_destroy]] static constinit ServiceHandler<IAudioFlinger, AudioSystem::AudioFlingerClient, media::IAudioFlingerService, AudioFlingerTraits> gAudioFlingerServiceHandler; sp<IAudioFlinger> AudioSystem::get_audio_flinger() { return getAudioFlingerImpl(); return gAudioFlingerServiceHandler.getService(); } sp<IAudioFlinger> AudioSystem::get_audio_flinger_for_fuzzer() { return getAudioFlingerImpl(false); return gAudioFlingerServiceHandler.getService(false /* canStartThreadPool */); } const sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() { // calling get_audio_flinger() will initialize gAudioFlingerClient if needed const sp<IAudioFlinger> af = get_audio_flinger(); if (af == 0) return 0; std::lock_guard _l(gMutex); return gAudioFlingerClient; sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() { return gAudioFlingerServiceHandler.getClient(); } void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) { if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) { ALOGE("%s: received a binder of type %s", __func__, String8(audioFlinger->getInterfaceDescriptor()).c_str()); return; } gAudioFlingerServiceHandler.setBinder(audioFlinger); } status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) { return gAudioFlingerServiceHandler.setLocalService(af); } sp<AudioIoDescriptor> AudioSystem::getIoDescriptor(audio_io_handle_t ioHandle) { Loading Loading @@ -557,14 +630,7 @@ void AudioSystem::AudioFlingerClient::clearIoCache() { } void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who __unused) { { std::lock_guard _l(AudioSystem::gMutex); AudioSystem::gAudioFlinger.clear(); } // clear output handles and stream to output map caches clearIoCache(); gAudioFlingerServiceHandler.clearService(); reportError(DEAD_OBJECT); ALOGW("AudioFlinger server died!"); Loading Loading @@ -1501,13 +1567,7 @@ status_t AudioSystem::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) void AudioSystem::clearAudioConfigCache() { // called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances ALOGV("clearAudioConfigCache()"); { std::lock_guard _l(gMutex); if (gAudioFlingerClient != 0) { gAudioFlingerClient->clearIoCache(); } gAudioFlinger.clear(); } gAudioFlingerServiceHandler.clearService(); clearAudioPolicyService(); } Loading media/libaudioclient/include/media/AudioSystem.h +7 −8 Original line number Diff line number Diff line Loading @@ -100,6 +100,10 @@ class AudioSystem friend class AudioFlingerClient; friend class AudioPolicyServiceClient; friend class CaptureStateListenerImpl; template <typename ServiceInterface, typename Client, typename AidlInterface, typename ServiceTraits> friend class ServiceHandler; public: // FIXME Declare in binder opcode order, similarly to IAudioFlinger.h and IAudioFlinger.cpp Loading Loading @@ -781,8 +785,6 @@ public: static int32_t getAAudioHardwareBurstMinUsec(); private: class AudioFlingerClient: public IBinder::DeathRecipient, public media::BnAudioFlingerClient { public: Loading Loading @@ -892,19 +894,16 @@ private: std::set<sp<AudioVolumeGroupCallback>> mAudioVolumeGroupCallbacks GUARDED_BY(mMutex); }; private: static audio_io_handle_t getOutput(audio_stream_type_t stream); static const sp<AudioFlingerClient> getAudioFlingerClient(); static sp<AudioFlingerClient> getAudioFlingerClient(); static sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle); static const sp<IAudioFlinger> getAudioFlingerImpl(bool canStartThreadPool); // Invokes all registered error callbacks with the given error code. static void reportError(status_t err); [[clang::no_destroy]] static std::mutex gMutex; [[clang::no_destroy]] static sp<IAudioFlinger> gAudioFlinger GUARDED_BY(gMutex); [[clang::no_destroy]] static sp<IBinder> gAudioFlingerBinder GUARDED_BY(gMutex); [[clang::no_destroy]] static sp<IAudioFlinger> gLocalAudioFlinger GUARDED_BY(gMutex); [[clang::no_destroy]] static sp<AudioFlingerClient> gAudioFlingerClient GUARDED_BY(gMutex); static dynamic_policy_callback gDynPolicyCallback GUARDED_BY(gMutex); static record_config_callback gRecordConfigCallback GUARDED_BY(gMutex); static routing_callback gRoutingCallback GUARDED_BY(gMutex); Loading Loading
media/libaudioclient/AudioSystem.cpp +143 −83 Original line number Diff line number Diff line Loading @@ -66,10 +66,6 @@ using media::audio::common::AudioUsage; using media::audio::common::Int; std::mutex AudioSystem::gMutex; sp<IAudioFlinger> AudioSystem::gAudioFlinger; sp<IBinder> AudioSystem::gAudioFlingerBinder; sp<IAudioFlinger> AudioSystem::gLocalAudioFlinger; sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient; dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL; record_config_callback AudioSystem::gRecordConfigCallback = NULL; routing_callback AudioSystem::gRoutingCallback = NULL; Loading @@ -89,90 +85,167 @@ sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient // from the system server. // This allows specific isolated processes to access the audio system. Currently used only for the // HotwordDetectionService. void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) { if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) { ALOGE("setAudioFlingerBinder: received a binder of type %s", String8(audioFlinger->getInterfaceDescriptor()).c_str()); return; } std::lock_guard _l(gMutex); if (gAudioFlinger != nullptr) { ALOGW("setAudioFlingerBinder: ignoring; AudioFlinger connection already established."); return; } gAudioFlingerBinder = audioFlinger; } status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) { std::lock_guard _l(gMutex); if (gAudioFlinger != nullptr) return INVALID_OPERATION; gLocalAudioFlinger = af; return OK; } template <typename ServiceInterface, typename Client, typename AidlInterface, typename ServiceTraits> class ServiceHandler { public: sp<ServiceInterface> getService(bool canStartThreadPool = true) EXCLUDES(mMutex) NO_THREAD_SAFETY_ANALYSIS { // std::unique_ptr sp<ServiceInterface> service; sp<Client> client; // establish binder interface to AudioFlinger service const sp<IAudioFlinger> AudioSystem::getAudioFlingerImpl(bool canStartThreadPool = true) { sp<IAudioFlinger> af; sp<AudioFlingerClient> afc; bool reportNoError = false; { std::lock_guard _l(gMutex); if (gAudioFlinger != nullptr) { return gAudioFlinger; std::lock_guard _l(mMutex); if (mService != nullptr) { return mService; } } if (gAudioFlingerClient == nullptr) { gAudioFlingerClient = sp<AudioFlingerClient>::make(); std::unique_lock ul_only1thread(mSingleGetter); std::unique_lock ul(mMutex); if (mService != nullptr) { return mService; } if (mClient == nullptr) { mClient = sp<Client>::make(); } else { reportNoError = true; } while (true) { mService = mLocalService; if (mService != nullptr) break; if (gLocalAudioFlinger != nullptr) { gAudioFlinger = gLocalAudioFlinger; } else { sp<IBinder> binder; if (gAudioFlingerBinder != nullptr) { binder = gAudioFlingerBinder; } else { sp<IBinder> binder = mBinder; if (binder == nullptr) { sp <IServiceManager> sm = defaultServiceManager(); binder = sm->waitForService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME)); binder = sm->checkService(String16(ServiceTraits::SERVICE_NAME)); if (binder == nullptr) { return nullptr; ALOGD("%s: waiting for %s", __func__, ServiceTraits::SERVICE_NAME); // if the condition variable is present, setLocalService() and // setBinder() is allowed to use it to notify us. if (mCvGetter == nullptr) { mCvGetter = std::make_shared<std::condition_variable>(); } mCvGetter->wait_for(ul, std::chrono::seconds(1)); continue; } } binder->linkToDeath(gAudioFlingerClient); const auto afs = interface_cast<media::IAudioFlingerService>(binder); LOG_ALWAYS_FATAL_IF(afs == nullptr); gAudioFlinger = sp<AudioFlingerClientAdapter>::make(afs); binder->linkToDeath(mClient); auto aidlInterface = interface_cast<AidlInterface>(binder); LOG_ALWAYS_FATAL_IF(aidlInterface == nullptr); if constexpr (std::is_same_v<ServiceInterface, AidlInterface>) { mService = std::move(aidlInterface); } else /* constexpr */ { mService = ServiceTraits::createServiceAdapter(aidlInterface); } afc = gAudioFlingerClient; af = gAudioFlinger; // Make sure callbacks can be received by gAudioFlingerClient break; } if (mCvGetter) mCvGetter.reset(); // remove condition variable. client = mClient; service = mService; // Make sure callbacks can be received by the client if (canStartThreadPool) { ProcessState::self()->startThreadPool(); } ul.unlock(); ul_only1thread.unlock(); ServiceTraits::onServiceCreate(service, client); if (reportNoError) AudioSystem::reportError(NO_ERROR); return service; } status_t setLocalService(const sp<ServiceInterface>& service) EXCLUDES(mMutex) { std::lock_guard _l(mMutex); // we allow clearing once set, but not a double non-null set. if (mService != nullptr && service != nullptr) return INVALID_OPERATION; mLocalService = service; if (mCvGetter) mCvGetter->notify_one(); return OK; } sp<Client> getClient() EXCLUDES(mMutex) { const auto service = getService(); if (service == nullptr) return nullptr; std::lock_guard _l(mMutex); return mClient; } void setBinder(const sp<IBinder>& binder) EXCLUDES(mMutex) { std::lock_guard _l(mMutex); if (mService != nullptr) { ALOGW("%s: ignoring; %s connection already established.", __func__, ServiceTraits::SERVICE_NAME); return; } mBinder = binder; if (mCvGetter) mCvGetter->notify_one(); } void clearService() EXCLUDES(mMutex) { std::lock_guard _l(mMutex); mService.clear(); if (mClient) ServiceTraits::onClearService(mClient); } private: std::mutex mSingleGetter; std::mutex mMutex; std::shared_ptr<std::condition_variable> mCvGetter GUARDED_BY(mMutex); sp<IBinder> mBinder GUARDED_BY(mMutex); sp<ServiceInterface> mLocalService GUARDED_BY(mMutex); sp<ServiceInterface> mService GUARDED_BY(mMutex); sp<Client> mClient GUARDED_BY(mMutex); }; struct AudioFlingerTraits { static void onServiceCreate( const sp<IAudioFlinger>& af, const sp<AudioSystem::AudioFlingerClient>& afc) { const int64_t token = IPCThreadState::self()->clearCallingIdentity(); af->registerClient(afc); IPCThreadState::self()->restoreCallingIdentity(token); if (reportNoError) reportError(NO_ERROR); return af; } static sp<IAudioFlinger> createServiceAdapter( const sp<media::IAudioFlingerService>& aidlInterface) { return sp<AudioFlingerClientAdapter>::make(aidlInterface); } static void onClearService(const sp<AudioSystem::AudioFlingerClient>& afc) { afc->clearIoCache(); } static constexpr const char* SERVICE_NAME = IAudioFlinger::DEFAULT_SERVICE_NAME; }; [[clang::no_destroy]] static constinit ServiceHandler<IAudioFlinger, AudioSystem::AudioFlingerClient, media::IAudioFlingerService, AudioFlingerTraits> gAudioFlingerServiceHandler; sp<IAudioFlinger> AudioSystem::get_audio_flinger() { return getAudioFlingerImpl(); return gAudioFlingerServiceHandler.getService(); } sp<IAudioFlinger> AudioSystem::get_audio_flinger_for_fuzzer() { return getAudioFlingerImpl(false); return gAudioFlingerServiceHandler.getService(false /* canStartThreadPool */); } const sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() { // calling get_audio_flinger() will initialize gAudioFlingerClient if needed const sp<IAudioFlinger> af = get_audio_flinger(); if (af == 0) return 0; std::lock_guard _l(gMutex); return gAudioFlingerClient; sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() { return gAudioFlingerServiceHandler.getClient(); } void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) { if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) { ALOGE("%s: received a binder of type %s", __func__, String8(audioFlinger->getInterfaceDescriptor()).c_str()); return; } gAudioFlingerServiceHandler.setBinder(audioFlinger); } status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) { return gAudioFlingerServiceHandler.setLocalService(af); } sp<AudioIoDescriptor> AudioSystem::getIoDescriptor(audio_io_handle_t ioHandle) { Loading Loading @@ -557,14 +630,7 @@ void AudioSystem::AudioFlingerClient::clearIoCache() { } void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who __unused) { { std::lock_guard _l(AudioSystem::gMutex); AudioSystem::gAudioFlinger.clear(); } // clear output handles and stream to output map caches clearIoCache(); gAudioFlingerServiceHandler.clearService(); reportError(DEAD_OBJECT); ALOGW("AudioFlinger server died!"); Loading Loading @@ -1501,13 +1567,7 @@ status_t AudioSystem::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) void AudioSystem::clearAudioConfigCache() { // called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances ALOGV("clearAudioConfigCache()"); { std::lock_guard _l(gMutex); if (gAudioFlingerClient != 0) { gAudioFlingerClient->clearIoCache(); } gAudioFlinger.clear(); } gAudioFlingerServiceHandler.clearService(); clearAudioPolicyService(); } Loading
media/libaudioclient/include/media/AudioSystem.h +7 −8 Original line number Diff line number Diff line Loading @@ -100,6 +100,10 @@ class AudioSystem friend class AudioFlingerClient; friend class AudioPolicyServiceClient; friend class CaptureStateListenerImpl; template <typename ServiceInterface, typename Client, typename AidlInterface, typename ServiceTraits> friend class ServiceHandler; public: // FIXME Declare in binder opcode order, similarly to IAudioFlinger.h and IAudioFlinger.cpp Loading Loading @@ -781,8 +785,6 @@ public: static int32_t getAAudioHardwareBurstMinUsec(); private: class AudioFlingerClient: public IBinder::DeathRecipient, public media::BnAudioFlingerClient { public: Loading Loading @@ -892,19 +894,16 @@ private: std::set<sp<AudioVolumeGroupCallback>> mAudioVolumeGroupCallbacks GUARDED_BY(mMutex); }; private: static audio_io_handle_t getOutput(audio_stream_type_t stream); static const sp<AudioFlingerClient> getAudioFlingerClient(); static sp<AudioFlingerClient> getAudioFlingerClient(); static sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle); static const sp<IAudioFlinger> getAudioFlingerImpl(bool canStartThreadPool); // Invokes all registered error callbacks with the given error code. static void reportError(status_t err); [[clang::no_destroy]] static std::mutex gMutex; [[clang::no_destroy]] static sp<IAudioFlinger> gAudioFlinger GUARDED_BY(gMutex); [[clang::no_destroy]] static sp<IBinder> gAudioFlingerBinder GUARDED_BY(gMutex); [[clang::no_destroy]] static sp<IAudioFlinger> gLocalAudioFlinger GUARDED_BY(gMutex); [[clang::no_destroy]] static sp<AudioFlingerClient> gAudioFlingerClient GUARDED_BY(gMutex); static dynamic_policy_callback gDynPolicyCallback GUARDED_BY(gMutex); static record_config_callback gRecordConfigCallback GUARDED_BY(gMutex); static routing_callback gRoutingCallback GUARDED_BY(gMutex); Loading