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