Home | History | Annotate | Download | only in audioflinger
      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