1 /* 2 ** 3 ** Copyright 2022, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #pragma once 19 20 #include "IAfPatchPanel.h" 21 22 #include <utils/RefBase.h> // avoid transitive dependency 23 #include <utils/Thread.h> // avoid transitive dependency 24 25 #include <deque> 26 #include <mutex> // avoid transitive dependency 27 28 namespace android { 29 30 class Command; 31 32 // Thread to execute create and release patch commands asynchronously. This is needed because 33 // IAfPatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service 34 // with mutex locked and effect management requires to call back into audio policy service 35 class PatchCommandThread : public Thread { 36 public: 37 38 enum { 39 CREATE_AUDIO_PATCH, 40 RELEASE_AUDIO_PATCH, 41 UPDATE_AUDIO_PATCH, 42 }; 43 44 class PatchCommandListener : public virtual RefBase { 45 public: 46 virtual void onCreateAudioPatch(audio_patch_handle_t handle, 47 const IAfPatchPanel::Patch& patch) = 0; 48 virtual void onReleaseAudioPatch(audio_patch_handle_t handle) = 0; 49 virtual void onUpdateAudioPatch(audio_patch_handle_t oldHandle, 50 audio_patch_handle_t newHandle, 51 const IAfPatchPanel::Patch& patch) = 0; 52 }; 53 PatchCommandThread()54 PatchCommandThread() : Thread(false /* canCallJava */) {} 55 ~PatchCommandThread() override; 56 57 void addListener(const sp<PatchCommandListener>& listener) 58 EXCLUDES_PatchCommandThread_ListenerMutex; 59 60 void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) 61 EXCLUDES_PatchCommandThread_Mutex; 62 void releaseAudioPatch(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex; 63 void updateAudioPatch(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle, 64 const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex; 65 66 // Thread virtuals 67 void onFirstRef() override; 68 bool threadLoop() override; 69 70 void exit(); 71 72 void createAudioPatchCommand(audio_patch_handle_t handle, 73 const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex; 74 void releaseAudioPatchCommand(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex; 75 void updateAudioPatchCommand(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle, 76 const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex; 77 78 private: 79 class CommandData; 80 81 // Command type received from the PatchPanel 82 class Command: public RefBase { 83 public: 84 Command() = default; Command(int command,const sp<CommandData> & data)85 Command(int command, const sp<CommandData>& data) 86 : mCommand(command), mData(data) {} 87 88 const int mCommand = -1; 89 const sp<CommandData> mData; 90 }; 91 92 class CommandData: public RefBase {}; 93 94 class CreateAudioPatchData : public CommandData { 95 public: CreateAudioPatchData(audio_patch_handle_t handle,const IAfPatchPanel::Patch & patch)96 CreateAudioPatchData(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) 97 : mHandle(handle), mPatch(patch) {} 98 99 const audio_patch_handle_t mHandle; 100 const IAfPatchPanel::Patch mPatch; 101 }; 102 103 class ReleaseAudioPatchData : public CommandData { 104 public: ReleaseAudioPatchData(audio_patch_handle_t handle)105 explicit ReleaseAudioPatchData(audio_patch_handle_t handle) 106 : mHandle(handle) {} 107 108 audio_patch_handle_t mHandle; 109 }; 110 111 class UpdateAudioPatchData : public CommandData { 112 public: UpdateAudioPatchData(audio_patch_handle_t oldHandle,audio_patch_handle_t newHandle,const IAfPatchPanel::Patch & patch)113 UpdateAudioPatchData(audio_patch_handle_t oldHandle, 114 audio_patch_handle_t newHandle, 115 const IAfPatchPanel::Patch& patch) 116 : mOldHandle(oldHandle), mNewHandle(newHandle), mPatch(patch) {} 117 118 const audio_patch_handle_t mOldHandle; 119 const audio_patch_handle_t mNewHandle; 120 const IAfPatchPanel::Patch mPatch; 121 }; 122 123 void sendCommand(const sp<Command>& command) EXCLUDES_PatchCommandThread_Mutex; 124 mutex()125 audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::PatchCommandThread_Mutex) { 126 return mMutex; 127 } listenerMutex()128 audio_utils::mutex& listenerMutex() const 129 RETURN_CAPABILITY(audio_utils::PatchCommandThread_ListenerMutex) { 130 return mListenerMutex; 131 } 132 133 mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kPatchCommandThread_Mutex}; 134 audio_utils::condition_variable mWaitWorkCV; 135 std::deque<sp<Command>> mCommands GUARDED_BY(mutex()); // list of pending commands 136 137 mutable audio_utils::mutex mListenerMutex{ 138 audio_utils::MutexOrder::kPatchCommandThread_ListenerMutex}; 139 std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(listenerMutex()); 140 }; 141 142 } // namespace android 143