/* ** ** Copyright 2022, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #pragma once #include "IAfPatchPanel.h" #include // avoid transitive dependency #include // avoid transitive dependency #include #include // avoid transitive dependency namespace android { class Command; // Thread to execute create and release patch commands asynchronously. This is needed because // IAfPatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service // with mutex locked and effect management requires to call back into audio policy service class PatchCommandThread : public Thread { public: enum { CREATE_AUDIO_PATCH, RELEASE_AUDIO_PATCH, UPDATE_AUDIO_PATCH, }; class PatchCommandListener : public virtual RefBase { public: virtual void onCreateAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) = 0; virtual void onReleaseAudioPatch(audio_patch_handle_t handle) = 0; virtual void onUpdateAudioPatch(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) = 0; }; PatchCommandThread() : Thread(false /* canCallJava */) {} ~PatchCommandThread() override; void addListener(const sp& listener) EXCLUDES_PatchCommandThread_ListenerMutex; void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex; void releaseAudioPatch(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex; void updateAudioPatch(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex; // Thread virtuals void onFirstRef() override; bool threadLoop() override; void exit(); void createAudioPatchCommand(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex; void releaseAudioPatchCommand(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex; void updateAudioPatchCommand(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex; private: class CommandData; // Command type received from the PatchPanel class Command: public RefBase { public: Command() = default; Command(int command, const sp& data) : mCommand(command), mData(data) {} const int mCommand = -1; const sp mData; }; class CommandData: public RefBase {}; class CreateAudioPatchData : public CommandData { public: CreateAudioPatchData(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) : mHandle(handle), mPatch(patch) {} const audio_patch_handle_t mHandle; const IAfPatchPanel::Patch mPatch; }; class ReleaseAudioPatchData : public CommandData { public: explicit ReleaseAudioPatchData(audio_patch_handle_t handle) : mHandle(handle) {} audio_patch_handle_t mHandle; }; class UpdateAudioPatchData : public CommandData { public: UpdateAudioPatchData(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) : mOldHandle(oldHandle), mNewHandle(newHandle), mPatch(patch) {} const audio_patch_handle_t mOldHandle; const audio_patch_handle_t mNewHandle; const IAfPatchPanel::Patch mPatch; }; void sendCommand(const sp& command) EXCLUDES_PatchCommandThread_Mutex; audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::PatchCommandThread_Mutex) { return mMutex; } audio_utils::mutex& listenerMutex() const RETURN_CAPABILITY(audio_utils::PatchCommandThread_ListenerMutex) { return mListenerMutex; } mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kPatchCommandThread_Mutex}; audio_utils::condition_variable mWaitWorkCV; std::deque> mCommands GUARDED_BY(mutex()); // list of pending commands mutable audio_utils::mutex mListenerMutex{ audio_utils::MutexOrder::kPatchCommandThread_ListenerMutex}; std::vector> mListeners GUARDED_BY(listenerMutex()); }; } // namespace android