1 /* 2 ** 3 ** Copyright 2014, 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 #ifndef INCLUDING_FROM_AUDIOFLINGER_H 19 #error This header file should only be included from AudioFlinger.h 20 #endif 21 22 23 // PatchPanel is concealed within AudioFlinger, their lifetimes are the same. 24 class PatchPanel { 25 public: 26 class SoftwarePatch { 27 public: SoftwarePatch(const PatchPanel & patchPanel,audio_patch_handle_t patchHandle,audio_io_handle_t playbackThreadHandle,audio_io_handle_t recordThreadHandle)28 SoftwarePatch(const PatchPanel &patchPanel, audio_patch_handle_t patchHandle, 29 audio_io_handle_t playbackThreadHandle, audio_io_handle_t recordThreadHandle) 30 : mPatchPanel(patchPanel), mPatchHandle(patchHandle), 31 mPlaybackThreadHandle(playbackThreadHandle), 32 mRecordThreadHandle(recordThreadHandle) {} 33 SoftwarePatch(const SoftwarePatch&) = default; 34 SoftwarePatch& operator=(const SoftwarePatch&) = default; 35 36 // Must be called under AudioFlinger::mLock 37 status_t getLatencyMs_l(double *latencyMs) const; getPatchHandle()38 audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }; getPlaybackThreadHandle()39 audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; }; getRecordThreadHandle()40 audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; }; 41 private: 42 const PatchPanel &mPatchPanel; 43 const audio_patch_handle_t mPatchHandle; 44 const audio_io_handle_t mPlaybackThreadHandle; 45 const audio_io_handle_t mRecordThreadHandle; 46 }; 47 PatchPanel(AudioFlinger * audioFlinger)48 explicit PatchPanel(AudioFlinger* audioFlinger) : mAudioFlinger(*audioFlinger) {} 49 50 /* List connected audio ports and their attributes */ 51 status_t listAudioPorts(unsigned int *num_ports, 52 struct audio_port *ports); 53 54 /* Get supported attributes for a given audio port */ 55 status_t getAudioPort(struct audio_port *port); 56 57 /* Create a patch between several source and sink ports */ 58 status_t createAudioPatch(const struct audio_patch *patch, 59 audio_patch_handle_t *handle); 60 61 /* Release a patch */ 62 status_t releaseAudioPatch(audio_patch_handle_t handle); 63 64 /* List connected audio devices and they attributes */ 65 status_t listAudioPatches(unsigned int *num_patches, 66 struct audio_patch *patches); 67 68 // Retrieves all currently estrablished software patches for a stream 69 // opened on an intermediate module. 70 status_t getDownstreamSoftwarePatches(audio_io_handle_t stream, 71 std::vector<SoftwarePatch> *patches) const; 72 73 // Notifies patch panel about all opened and closed streams. 74 void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream); 75 void notifyStreamClosed(audio_io_handle_t stream); 76 77 void dump(int fd) const; 78 79 template<typename ThreadType, typename TrackType> 80 class Endpoint final { 81 public: 82 Endpoint() = default; 83 Endpoint(const Endpoint&) = delete; 84 Endpoint& operator=(const Endpoint& other) noexcept { 85 mThread = other.mThread; 86 mCloseThread = other.mCloseThread; 87 mHandle = other.mHandle; 88 mTrack = other.mTrack; 89 return *this; 90 } Endpoint(Endpoint && other)91 Endpoint(Endpoint&& other) noexcept { swap(other); } 92 Endpoint& operator=(Endpoint&& other) noexcept { 93 swap(other); 94 return *this; 95 } ~Endpoint()96 ~Endpoint() { 97 ALOGE_IF(mHandle != AUDIO_PATCH_HANDLE_NONE, 98 "A non empty Patch Endpoint leaked, handle %d", mHandle); 99 } 100 checkTrack(TrackType * trackOrNull)101 status_t checkTrack(TrackType *trackOrNull) const { 102 if (trackOrNull == nullptr) return NO_MEMORY; 103 return trackOrNull->initCheck(); 104 } handle()105 audio_patch_handle_t handle() const { return mHandle; } thread()106 sp<ThreadType> thread() const { return mThread; } track()107 sp<TrackType> track() const { return mTrack; } const_thread()108 sp<const ThreadType> const_thread() const { return mThread; } const_track()109 sp<const TrackType> const_track() const { return mTrack; } 110 closeConnections(PatchPanel * panel)111 void closeConnections(PatchPanel *panel) { 112 if (mHandle != AUDIO_PATCH_HANDLE_NONE) { 113 panel->releaseAudioPatch(mHandle); 114 mHandle = AUDIO_PATCH_HANDLE_NONE; 115 } 116 if (mThread != 0) { 117 if (mTrack != 0) { 118 mThread->deletePatchTrack(mTrack); 119 } 120 if (mCloseThread) { 121 panel->mAudioFlinger.closeThreadInternal_l(mThread); 122 } 123 } 124 } handlePtr()125 audio_patch_handle_t* handlePtr() { return &mHandle; } 126 void setThread(const sp<ThreadType>& thread, bool closeThread = true) { 127 mThread = thread; 128 mCloseThread = closeThread; 129 } 130 template <typename T> setTrackAndPeer(const sp<TrackType> & track,const sp<T> & peer,bool holdReference)131 void setTrackAndPeer(const sp<TrackType>& track, const sp<T> &peer, bool holdReference) { 132 mTrack = track; 133 mThread->addPatchTrack(mTrack); 134 mTrack->setPeerProxy(peer, holdReference); 135 mClearPeerProxy = holdReference; 136 } clearTrackPeer()137 void clearTrackPeer() { if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy(); } stopTrack()138 void stopTrack() { if (mTrack) mTrack->stop(); } 139 swap(Endpoint & other)140 void swap(Endpoint &other) noexcept { 141 using std::swap; 142 swap(mThread, other.mThread); 143 swap(mCloseThread, other.mCloseThread); 144 swap(mClearPeerProxy, other.mClearPeerProxy); 145 swap(mHandle, other.mHandle); 146 swap(mTrack, other.mTrack); 147 } 148 swap(Endpoint & a,Endpoint & b)149 friend void swap(Endpoint &a, Endpoint &b) noexcept { 150 a.swap(b); 151 } 152 153 private: 154 sp<ThreadType> mThread; 155 bool mCloseThread = true; 156 bool mClearPeerProxy = true; 157 audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE; 158 sp<TrackType> mTrack; 159 }; 160 161 class Patch final { 162 public: Patch(const struct audio_patch & patch)163 explicit Patch(const struct audio_patch &patch) : mAudioPatch(patch) {} 164 Patch() = default; 165 ~Patch(); Patch(const Patch & other)166 Patch(const Patch& other) noexcept { 167 mAudioPatch = other.mAudioPatch; 168 mHalHandle = other.mHalHandle; 169 mPlayback = other.mPlayback; 170 mRecord = other.mRecord; 171 mThread = other.mThread; 172 } Patch(Patch && other)173 Patch(Patch&& other) noexcept { swap(other); } 174 Patch& operator=(Patch&& other) noexcept { 175 swap(other); 176 return *this; 177 } 178 swap(Patch & other)179 void swap(Patch &other) noexcept { 180 using std::swap; 181 swap(mAudioPatch, other.mAudioPatch); 182 swap(mHalHandle, other.mHalHandle); 183 swap(mPlayback, other.mPlayback); 184 swap(mRecord, other.mRecord); 185 swap(mThread, other.mThread); 186 } 187 swap(Patch & a,Patch & b)188 friend void swap(Patch &a, Patch &b) noexcept { 189 a.swap(b); 190 } 191 192 status_t createConnections(PatchPanel *panel); 193 void clearConnections(PatchPanel *panel); isSoftware()194 bool isSoftware() const { 195 return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE || 196 mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; } 197 setThread(sp<ThreadBase> thread)198 void setThread(sp<ThreadBase> thread) { mThread = thread; } thread()199 wp<ThreadBase> thread() const { return mThread; } 200 201 // returns the latency of the patch (from record to playback). 202 status_t getLatencyMs(double *latencyMs) const; 203 204 String8 dump(audio_patch_handle_t myHandle) const; 205 206 // Note that audio_patch::id is only unique within a HAL module 207 struct audio_patch mAudioPatch; 208 // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0 209 audio_patch_handle_t mHalHandle = AUDIO_PATCH_HANDLE_NONE; 210 // below members are used by a software audio patch connecting a source device from a 211 // given audio HW module to a sink device on an other audio HW module. 212 // the objects are created by createConnections() and released by clearConnections() 213 // playback thread is created if no existing playback thread can be used 214 // connects playback thread output to sink device 215 Endpoint<PlaybackThread, PlaybackThread::PatchTrack> mPlayback; 216 // connects source device to record thread input 217 Endpoint<RecordThread, RecordThread::PatchRecord> mRecord; 218 219 wp<ThreadBase> mThread; 220 }; 221 222 // Call with AudioFlinger mLock held patches_l()223 std::map<audio_patch_handle_t, Patch>& patches_l() { return mPatches; } 224 225 private: 226 AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module); 227 sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module); 228 void addSoftwarePatchToInsertedModules( 229 audio_module_handle_t module, audio_patch_handle_t handle); 230 void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle); 231 void erasePatch(audio_patch_handle_t handle); 232 233 AudioFlinger &mAudioFlinger; 234 std::map<audio_patch_handle_t, Patch> mPatches; 235 236 // This map allows going from a thread to "downstream" software patches 237 // when a processing module inserted in between. Example: 238 // 239 // from map value.streams map key 240 // [Mixer thread] --> [Virtual output device] --> [Processing module] ---\ 241 // [Harware module] <-- [Physical output device] <-- [S/W Patch] <--/ 242 // from map value.sw_patches 243 // 244 // This allows the mixer thread to look up the threads of the software patch 245 // for propagating timing info, parameters, etc. 246 // 247 // The current assumptions are: 248 // 1) The processing module acts as a mixer with several outputs which 249 // represent differently downmixed and / or encoded versions of the same 250 // mixed stream. There is no 1:1 correspondence between the input streams 251 // and the software patches, but rather a N:N correspondence between 252 // a group of streams and a group of patches. 253 // 2) There are only a couple of inserted processing modules in the system, 254 // so when looking for a stream or patch handle we can iterate over 255 // all modules. 256 struct ModuleConnections { 257 std::set<audio_io_handle_t> streams; 258 std::set<audio_patch_handle_t> sw_patches; 259 }; 260 std::map<audio_module_handle_t, ModuleConnections> mInsertedModules; 261 }; 262