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