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: 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; 38 audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }; 39 audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; }; 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 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 private: 80 template<typename ThreadType, typename TrackType> 81 class Endpoint { 82 public: 83 Endpoint() = default; 84 Endpoint(const Endpoint&) = delete; 85 Endpoint& operator=(const Endpoint&) = delete; 86 Endpoint(Endpoint&& other) noexcept { swap(other); } 87 Endpoint& operator=(Endpoint&& other) noexcept { 88 swap(other); 89 return *this; 90 } 91 ~Endpoint() { 92 ALOGE_IF(mHandle != AUDIO_PATCH_HANDLE_NONE, 93 "A non empty Patch Endpoint leaked, handle %d", mHandle); 94 } 95 96 status_t checkTrack(TrackType *trackOrNull) const { 97 if (trackOrNull == nullptr) return NO_MEMORY; 98 return trackOrNull->initCheck(); 99 } 100 audio_patch_handle_t handle() const { return mHandle; } 101 sp<ThreadType> thread() { return mThread; } 102 sp<TrackType> track() { return mTrack; } 103 sp<const ThreadType> const_thread() const { return mThread; } 104 sp<const TrackType> const_track() const { return mTrack; } 105 106 void closeConnections(PatchPanel *panel) { 107 if (mHandle != AUDIO_PATCH_HANDLE_NONE) { 108 panel->releaseAudioPatch(mHandle); 109 mHandle = AUDIO_PATCH_HANDLE_NONE; 110 } 111 if (mThread != 0) { 112 if (mTrack != 0) { 113 mThread->deletePatchTrack(mTrack); 114 } 115 if (mCloseThread) { 116 panel->mAudioFlinger.closeThreadInternal_l(mThread); 117 } 118 } 119 } 120 audio_patch_handle_t* handlePtr() { return &mHandle; } 121 void setThread(const sp<ThreadType>& thread, bool closeThread = true) { 122 mThread = thread; 123 mCloseThread = closeThread; 124 } 125 template <typename T> 126 void setTrackAndPeer(const sp<TrackType>& track, const sp<T> &peer) { 127 mTrack = track; 128 mThread->addPatchTrack(mTrack); 129 mTrack->setPeerProxy(peer, true /* holdReference */); 130 } 131 void clearTrackPeer() { if (mTrack) mTrack->clearPeerProxy(); } 132 void stopTrack() { if (mTrack) mTrack->stop(); } 133 134 void swap(Endpoint &other) noexcept { 135 using std::swap; 136 swap(mThread, other.mThread); 137 swap(mCloseThread, other.mCloseThread); 138 swap(mHandle, other.mHandle); 139 swap(mTrack, other.mTrack); 140 } 141 142 friend void swap(Endpoint &a, Endpoint &b) noexcept { 143 a.swap(b); 144 } 145 146 private: 147 sp<ThreadType> mThread; 148 bool mCloseThread = true; 149 audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE; 150 sp<TrackType> mTrack; 151 }; 152 153 class Patch { 154 public: 155 explicit Patch(const struct audio_patch &patch) : mAudioPatch(patch) {} 156 ~Patch(); 157 Patch(const Patch&) = delete; 158 Patch(Patch&&) = default; 159 Patch& operator=(const Patch&) = delete; 160 Patch& operator=(Patch&&) = default; 161 162 status_t createConnections(PatchPanel *panel); 163 void clearConnections(PatchPanel *panel); 164 bool isSoftware() const { 165 return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE || 166 mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; } 167 168 // returns the latency of the patch (from record to playback). 169 status_t getLatencyMs(double *latencyMs) const; 170 171 String8 dump(audio_patch_handle_t myHandle) const; 172 173 // Note that audio_patch::id is only unique within a HAL module 174 struct audio_patch mAudioPatch; 175 // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0 176 audio_patch_handle_t mHalHandle = AUDIO_PATCH_HANDLE_NONE; 177 // below members are used by a software audio patch connecting a source device from a 178 // given audio HW module to a sink device on an other audio HW module. 179 // the objects are created by createConnections() and released by clearConnections() 180 // playback thread is created if no existing playback thread can be used 181 // connects playback thread output to sink device 182 Endpoint<PlaybackThread, PlaybackThread::PatchTrack> mPlayback; 183 // connects source device to record thread input 184 Endpoint<RecordThread, RecordThread::PatchRecord> mRecord; 185 }; 186 187 AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module); 188 sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module); 189 void addSoftwarePatchToInsertedModules( 190 audio_module_handle_t module, audio_patch_handle_t handle); 191 void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle); 192 193 AudioFlinger &mAudioFlinger; 194 std::map<audio_patch_handle_t, Patch> mPatches; 195 196 // This map allows going from a thread to "downstream" software patches 197 // when a processing module inserted in between. Example: 198 // 199 // from map value.streams map key 200 // [Mixer thread] --> [Virtual output device] --> [Processing module] ---\ 201 // [Harware module] <-- [Physical output device] <-- [S/W Patch] <--/ 202 // from map value.sw_patches 203 // 204 // This allows the mixer thread to look up the threads of the software patch 205 // for propagating timing info, parameters, etc. 206 // 207 // The current assumptions are: 208 // 1) The processing module acts as a mixer with several outputs which 209 // represent differently downmixed and / or encoded versions of the same 210 // mixed stream. There is no 1:1 correspondence between the input streams 211 // and the software patches, but rather a N:N correspondence between 212 // a group of streams and a group of patches. 213 // 2) There are only a couple of inserted processing modules in the system, 214 // so when looking for a stream or patch handle we can iterate over 215 // all modules. 216 struct ModuleConnections { 217 std::set<audio_io_handle_t> streams; 218 std::set<audio_patch_handle_t> sw_patches; 219 }; 220 std::map<audio_module_handle_t, ModuleConnections> mInsertedModules; 221 }; 222