Loading services/audioflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ cc_library_shared { "FastThreadDumpState.cpp", "FastThreadState.cpp", "NBAIO_Tee.cpp", "PatchCommandThread.cpp", "PatchPanel.cpp", "PropertyUtils.cpp", "SpdifStreamOut.cpp", Loading services/audioflinger/AudioFlinger.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -323,7 +323,8 @@ AudioFlinger::AudioFlinger() mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes), mGlobalEffectEnableTime(0), mPatchPanel(this), mDeviceEffectManager(this), mPatchCommandThread(sp<PatchCommandThread>::make()), mDeviceEffectManager(sp<DeviceEffectManager>::make(*this)), mSystemReady(false) { // Move the audio session unique ID generator start base as time passes to limit risk of Loading Loading @@ -873,7 +874,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) mPatchPanel.dump(fd); mDeviceEffectManager.dump(fd); mDeviceEffectManager->dump(fd); // dump external setParameters auto dumpLogger = [fd](SimpleLog& logger, const char* name) { Loading Loading @@ -4069,7 +4070,7 @@ status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request, if (sessionId == AUDIO_SESSION_DEVICE) { sp<Client> client = registerPid(currentPid); ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress()); handle = mDeviceEffectManager.createEffect_l( handle = mDeviceEffectManager->createEffect_l( &descOut, device, client, effectClient, mPatchPanel.patches_l(), &enabledOut, &lStatus, probe, request.notifyFramesProcessed); if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) { Loading services/audioflinger/AudioFlinger.h +4 −1 Original line number Diff line number Diff line Loading @@ -634,6 +634,8 @@ using effect_buffer_t = int16_t; #include "Effects.h" #include "PatchCommandThread.h" #include "DeviceEffectManager.h" // Find io handle by session id. Loading Loading @@ -1012,7 +1014,8 @@ private: PatchPanel mPatchPanel; sp<EffectsFactoryHalInterface> mEffectsFactoryHal; DeviceEffectManager mDeviceEffectManager; const sp<PatchCommandThread> mPatchCommandThread; sp<DeviceEffectManager> mDeviceEffectManager; bool mSystemReady; std::atomic_bool mAudioPolicyReady{}; Loading services/audioflinger/DeviceEffectManager.cpp +1 −103 Original line number Diff line number Diff line Loading @@ -32,16 +32,6 @@ namespace android { using media::IEffectClient; void AudioFlinger::DeviceEffectManager::createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch) { ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x", __func__, handle, patch.mHalHandle, patch.mAudioPatch.num_sinks, patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0); mCommandThread->createAudioPatchCommand(handle, patch); } void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch) { ALOGV("%s handle %d mHalHandle %d device sink %08x", Loading @@ -55,11 +45,6 @@ void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t } } void AudioFlinger::DeviceEffectManager::releaseAudioPatch(audio_patch_handle_t handle) { ALOGV("%s", __func__); mCommandThread->releaseAudioPatchCommand(handle); } void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) { ALOGV("%s", __func__); Mutex::Autolock _l(mLock); Loading Loading @@ -116,7 +101,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l } } } if (enabled != NULL) { if (enabled != nullptr) { *enabled = (int)effect->isEnabled(); } *status = lStatus; Loading Loading @@ -208,91 +193,4 @@ bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle( return true; } // ----------- DeviceEffectManager::CommandThread implementation ---------- AudioFlinger::DeviceEffectManager::CommandThread::~CommandThread() { Mutex::Autolock _l(mLock); mCommands.clear(); } void AudioFlinger::DeviceEffectManager::CommandThread::onFirstRef() { run("DeviceEffectManage_CommandThread", ANDROID_PRIORITY_AUDIO); } bool AudioFlinger::DeviceEffectManager::CommandThread::threadLoop() { mLock.lock(); while (!exitPending()) { while (!mCommands.empty() && !exitPending()) { sp<Command> command = mCommands.front(); mCommands.pop_front(); mLock.unlock(); switch (command->mCommand) { case CREATE_AUDIO_PATCH: { CreateAudioPatchData *data = (CreateAudioPatchData *)command->mData.get(); ALOGV("CommandThread() processing create audio patch handle %d", data->mHandle); mManager.onCreateAudioPatch(data->mHandle, data->mPatch); } break; case RELEASE_AUDIO_PATCH: { ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mData.get(); ALOGV("CommandThread() processing release audio patch handle %d", data->mHandle); mManager.onReleaseAudioPatch(data->mHandle); } break; default: ALOGW("CommandThread() unknown command %d", command->mCommand); } mLock.lock(); } // At this stage we have either an empty command queue or the first command in the queue // has a finite delay. So unless we are exiting it is safe to wait. if (!exitPending()) { ALOGV("CommandThread() going to sleep"); mWaitWorkCV.wait(mLock); } } mLock.unlock(); return false; } void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(sp<Command> command) { Mutex::Autolock _l(mLock); mCommands.push_back(command); mWaitWorkCV.signal(); } void AudioFlinger::DeviceEffectManager::CommandThread::createAudioPatchCommand( audio_patch_handle_t handle, const PatchPanel::Patch& patch) { sp<Command> command = new Command(CREATE_AUDIO_PATCH, new CreateAudioPatchData(handle, patch)); ALOGV("CommandThread() adding create patch handle %d mHalHandle %d.", handle, patch.mHalHandle); sendCommand(command); } void AudioFlinger::DeviceEffectManager::CommandThread::releaseAudioPatchCommand( audio_patch_handle_t handle) { sp<Command> command = new Command(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle)); ALOGV("CommandThread() adding release patch"); sendCommand(command); } void AudioFlinger::DeviceEffectManager::CommandThread::exit() { ALOGV("CommandThread::exit"); { AutoMutex _l(mLock); requestExit(); mWaitWorkCV.signal(); } // Note that we can call it from the thread loop if all other references have been released // but it will safely return WOULD_BLOCK in this case requestExitAndWait(); } } // namespace android services/audioflinger/DeviceEffectManager.h +15 −86 Original line number Diff line number Diff line Loading @@ -20,14 +20,14 @@ #endif // DeviceEffectManager is concealed within AudioFlinger, their lifetimes are the same. class DeviceEffectManager { class DeviceEffectManager : public PatchCommandThread::PatchCommandListener { public: explicit DeviceEffectManager(AudioFlinger* audioFlinger) : mCommandThread(new CommandThread(*this)), mAudioFlinger(*audioFlinger), mMyCallback(new DeviceEffectManagerCallback(this)) {} explicit DeviceEffectManager(AudioFlinger& audioFlinger) : mAudioFlinger(audioFlinger), mMyCallback(new DeviceEffectManagerCallback(*this)) {} ~DeviceEffectManager() { mCommandThread->exit(); void onFirstRef() override { mAudioFlinger.mPatchCommandThread->addListener(this); } sp<EffectHandle> createEffect_l(effect_descriptor_t *descriptor, Loading @@ -39,8 +39,6 @@ public: status_t *status, bool probe, bool notifyFramesProcessed); void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch); void releaseAudioPatch(audio_patch_handle_t handle); size_t removeEffect(const sp<DeviceEffectProxy>& effect); status_t createEffectHal(const effect_uuid_t *pEffectUuid, Loading @@ -59,85 +57,16 @@ public: void dump(int fd); private: // Thread to execute create and release patch commands asynchronously. This is needed because // PatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service // with mutex locked and effect management requires to call back into audio policy service class Command; class CommandThread : public Thread { public: enum { CREATE_AUDIO_PATCH, RELEASE_AUDIO_PATCH, }; CommandThread(DeviceEffectManager& manager) : Thread(false), mManager(manager) {} ~CommandThread() override; // Thread virtuals void onFirstRef() override; bool threadLoop() override; void exit(); // PatchCommandThread::PatchCommandListener implementation void createAudioPatchCommand(audio_patch_handle_t handle, const PatchPanel::Patch& patch); void releaseAudioPatchCommand(audio_patch_handle_t handle); void onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch) override; void onReleaseAudioPatch(audio_patch_handle_t handle) override; private: class CommandData; // descriptor for requested tone playback event class Command: public RefBase { public: Command() = default; Command(int command, sp<CommandData> data) : mCommand(command), mData(data) {} int mCommand = -1; sp<CommandData> mData; }; class CommandData: public RefBase { public: virtual ~CommandData() = default; }; class CreateAudioPatchData : public CommandData { public: CreateAudioPatchData(audio_patch_handle_t handle, const PatchPanel::Patch& patch) : mHandle(handle), mPatch(patch) {} audio_patch_handle_t mHandle; const PatchPanel::Patch mPatch; }; class ReleaseAudioPatchData : public CommandData { public: ReleaseAudioPatchData(audio_patch_handle_t handle) : mHandle(handle) {} audio_patch_handle_t mHandle; }; void sendCommand(sp<Command> command); Mutex mLock; Condition mWaitWorkCV; std::deque <sp<Command>> mCommands; // list of pending commands DeviceEffectManager& mManager; }; void onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch); void onReleaseAudioPatch(audio_patch_handle_t handle); status_t checkEffectCompatibility(const effect_descriptor_t *desc); Mutex mLock; sp<CommandThread> mCommandThread; AudioFlinger &mAudioFlinger; const sp<DeviceEffectManagerCallback> mMyCallback; std::map<AudioDeviceTypeAddr, sp<DeviceEffectProxy>> mDeviceEffects; Loading @@ -145,8 +74,8 @@ private: class DeviceEffectManagerCallback : public EffectCallbackInterface { public: DeviceEffectManagerCallback(DeviceEffectManager *manager) : mManager(*manager) {} DeviceEffectManagerCallback(DeviceEffectManager& manager) : mManager(manager) {} status_t createEffectHal(const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId, Loading Loading
services/audioflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ cc_library_shared { "FastThreadDumpState.cpp", "FastThreadState.cpp", "NBAIO_Tee.cpp", "PatchCommandThread.cpp", "PatchPanel.cpp", "PropertyUtils.cpp", "SpdifStreamOut.cpp", Loading
services/audioflinger/AudioFlinger.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -323,7 +323,8 @@ AudioFlinger::AudioFlinger() mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes), mGlobalEffectEnableTime(0), mPatchPanel(this), mDeviceEffectManager(this), mPatchCommandThread(sp<PatchCommandThread>::make()), mDeviceEffectManager(sp<DeviceEffectManager>::make(*this)), mSystemReady(false) { // Move the audio session unique ID generator start base as time passes to limit risk of Loading Loading @@ -873,7 +874,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) mPatchPanel.dump(fd); mDeviceEffectManager.dump(fd); mDeviceEffectManager->dump(fd); // dump external setParameters auto dumpLogger = [fd](SimpleLog& logger, const char* name) { Loading Loading @@ -4069,7 +4070,7 @@ status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request, if (sessionId == AUDIO_SESSION_DEVICE) { sp<Client> client = registerPid(currentPid); ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress()); handle = mDeviceEffectManager.createEffect_l( handle = mDeviceEffectManager->createEffect_l( &descOut, device, client, effectClient, mPatchPanel.patches_l(), &enabledOut, &lStatus, probe, request.notifyFramesProcessed); if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) { Loading
services/audioflinger/AudioFlinger.h +4 −1 Original line number Diff line number Diff line Loading @@ -634,6 +634,8 @@ using effect_buffer_t = int16_t; #include "Effects.h" #include "PatchCommandThread.h" #include "DeviceEffectManager.h" // Find io handle by session id. Loading Loading @@ -1012,7 +1014,8 @@ private: PatchPanel mPatchPanel; sp<EffectsFactoryHalInterface> mEffectsFactoryHal; DeviceEffectManager mDeviceEffectManager; const sp<PatchCommandThread> mPatchCommandThread; sp<DeviceEffectManager> mDeviceEffectManager; bool mSystemReady; std::atomic_bool mAudioPolicyReady{}; Loading
services/audioflinger/DeviceEffectManager.cpp +1 −103 Original line number Diff line number Diff line Loading @@ -32,16 +32,6 @@ namespace android { using media::IEffectClient; void AudioFlinger::DeviceEffectManager::createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch) { ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x", __func__, handle, patch.mHalHandle, patch.mAudioPatch.num_sinks, patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0); mCommandThread->createAudioPatchCommand(handle, patch); } void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch) { ALOGV("%s handle %d mHalHandle %d device sink %08x", Loading @@ -55,11 +45,6 @@ void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t } } void AudioFlinger::DeviceEffectManager::releaseAudioPatch(audio_patch_handle_t handle) { ALOGV("%s", __func__); mCommandThread->releaseAudioPatchCommand(handle); } void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) { ALOGV("%s", __func__); Mutex::Autolock _l(mLock); Loading Loading @@ -116,7 +101,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l } } } if (enabled != NULL) { if (enabled != nullptr) { *enabled = (int)effect->isEnabled(); } *status = lStatus; Loading Loading @@ -208,91 +193,4 @@ bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle( return true; } // ----------- DeviceEffectManager::CommandThread implementation ---------- AudioFlinger::DeviceEffectManager::CommandThread::~CommandThread() { Mutex::Autolock _l(mLock); mCommands.clear(); } void AudioFlinger::DeviceEffectManager::CommandThread::onFirstRef() { run("DeviceEffectManage_CommandThread", ANDROID_PRIORITY_AUDIO); } bool AudioFlinger::DeviceEffectManager::CommandThread::threadLoop() { mLock.lock(); while (!exitPending()) { while (!mCommands.empty() && !exitPending()) { sp<Command> command = mCommands.front(); mCommands.pop_front(); mLock.unlock(); switch (command->mCommand) { case CREATE_AUDIO_PATCH: { CreateAudioPatchData *data = (CreateAudioPatchData *)command->mData.get(); ALOGV("CommandThread() processing create audio patch handle %d", data->mHandle); mManager.onCreateAudioPatch(data->mHandle, data->mPatch); } break; case RELEASE_AUDIO_PATCH: { ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mData.get(); ALOGV("CommandThread() processing release audio patch handle %d", data->mHandle); mManager.onReleaseAudioPatch(data->mHandle); } break; default: ALOGW("CommandThread() unknown command %d", command->mCommand); } mLock.lock(); } // At this stage we have either an empty command queue or the first command in the queue // has a finite delay. So unless we are exiting it is safe to wait. if (!exitPending()) { ALOGV("CommandThread() going to sleep"); mWaitWorkCV.wait(mLock); } } mLock.unlock(); return false; } void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(sp<Command> command) { Mutex::Autolock _l(mLock); mCommands.push_back(command); mWaitWorkCV.signal(); } void AudioFlinger::DeviceEffectManager::CommandThread::createAudioPatchCommand( audio_patch_handle_t handle, const PatchPanel::Patch& patch) { sp<Command> command = new Command(CREATE_AUDIO_PATCH, new CreateAudioPatchData(handle, patch)); ALOGV("CommandThread() adding create patch handle %d mHalHandle %d.", handle, patch.mHalHandle); sendCommand(command); } void AudioFlinger::DeviceEffectManager::CommandThread::releaseAudioPatchCommand( audio_patch_handle_t handle) { sp<Command> command = new Command(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle)); ALOGV("CommandThread() adding release patch"); sendCommand(command); } void AudioFlinger::DeviceEffectManager::CommandThread::exit() { ALOGV("CommandThread::exit"); { AutoMutex _l(mLock); requestExit(); mWaitWorkCV.signal(); } // Note that we can call it from the thread loop if all other references have been released // but it will safely return WOULD_BLOCK in this case requestExitAndWait(); } } // namespace android
services/audioflinger/DeviceEffectManager.h +15 −86 Original line number Diff line number Diff line Loading @@ -20,14 +20,14 @@ #endif // DeviceEffectManager is concealed within AudioFlinger, their lifetimes are the same. class DeviceEffectManager { class DeviceEffectManager : public PatchCommandThread::PatchCommandListener { public: explicit DeviceEffectManager(AudioFlinger* audioFlinger) : mCommandThread(new CommandThread(*this)), mAudioFlinger(*audioFlinger), mMyCallback(new DeviceEffectManagerCallback(this)) {} explicit DeviceEffectManager(AudioFlinger& audioFlinger) : mAudioFlinger(audioFlinger), mMyCallback(new DeviceEffectManagerCallback(*this)) {} ~DeviceEffectManager() { mCommandThread->exit(); void onFirstRef() override { mAudioFlinger.mPatchCommandThread->addListener(this); } sp<EffectHandle> createEffect_l(effect_descriptor_t *descriptor, Loading @@ -39,8 +39,6 @@ public: status_t *status, bool probe, bool notifyFramesProcessed); void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch); void releaseAudioPatch(audio_patch_handle_t handle); size_t removeEffect(const sp<DeviceEffectProxy>& effect); status_t createEffectHal(const effect_uuid_t *pEffectUuid, Loading @@ -59,85 +57,16 @@ public: void dump(int fd); private: // Thread to execute create and release patch commands asynchronously. This is needed because // PatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service // with mutex locked and effect management requires to call back into audio policy service class Command; class CommandThread : public Thread { public: enum { CREATE_AUDIO_PATCH, RELEASE_AUDIO_PATCH, }; CommandThread(DeviceEffectManager& manager) : Thread(false), mManager(manager) {} ~CommandThread() override; // Thread virtuals void onFirstRef() override; bool threadLoop() override; void exit(); // PatchCommandThread::PatchCommandListener implementation void createAudioPatchCommand(audio_patch_handle_t handle, const PatchPanel::Patch& patch); void releaseAudioPatchCommand(audio_patch_handle_t handle); void onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch) override; void onReleaseAudioPatch(audio_patch_handle_t handle) override; private: class CommandData; // descriptor for requested tone playback event class Command: public RefBase { public: Command() = default; Command(int command, sp<CommandData> data) : mCommand(command), mData(data) {} int mCommand = -1; sp<CommandData> mData; }; class CommandData: public RefBase { public: virtual ~CommandData() = default; }; class CreateAudioPatchData : public CommandData { public: CreateAudioPatchData(audio_patch_handle_t handle, const PatchPanel::Patch& patch) : mHandle(handle), mPatch(patch) {} audio_patch_handle_t mHandle; const PatchPanel::Patch mPatch; }; class ReleaseAudioPatchData : public CommandData { public: ReleaseAudioPatchData(audio_patch_handle_t handle) : mHandle(handle) {} audio_patch_handle_t mHandle; }; void sendCommand(sp<Command> command); Mutex mLock; Condition mWaitWorkCV; std::deque <sp<Command>> mCommands; // list of pending commands DeviceEffectManager& mManager; }; void onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch); void onReleaseAudioPatch(audio_patch_handle_t handle); status_t checkEffectCompatibility(const effect_descriptor_t *desc); Mutex mLock; sp<CommandThread> mCommandThread; AudioFlinger &mAudioFlinger; const sp<DeviceEffectManagerCallback> mMyCallback; std::map<AudioDeviceTypeAddr, sp<DeviceEffectProxy>> mDeviceEffects; Loading @@ -145,8 +74,8 @@ private: class DeviceEffectManagerCallback : public EffectCallbackInterface { public: DeviceEffectManagerCallback(DeviceEffectManager *manager) : mManager(*manager) {} DeviceEffectManagerCallback(DeviceEffectManager& manager) : mManager(manager) {} status_t createEffectHal(const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId, Loading