1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 // The following includes are required because we have class definitions below 20 // for EndPoint and Patch, which precludes using a forward declaration only. 21 #include "IAfThread.h" // IAfThreadBase IAfMmapThread IAfPlaybackThread IAfRecordThread 22 #include "IAfTrack.h" // IAfPatchRecord IAfPatchTrack 23 24 #include <datapath/AudioHwDevice.h> 25 #include <media/DeviceDescriptorBase.h> 26 #include <utils/Log.h> // ALOG used in this file 27 #include <utils/RefBase.h> // avoid transitive dependency 28 #include <utils/Thread.h> 29 30 namespace android { 31 32 class IAfPatchPanel; 33 class PatchCommandThread; 34 35 class SoftwarePatch { 36 public: SoftwarePatch(const sp<const IAfPatchPanel> & patchPanel,audio_patch_handle_t patchHandle,audio_io_handle_t playbackThreadHandle,audio_io_handle_t recordThreadHandle)37 SoftwarePatch( 38 const sp<const IAfPatchPanel>& patchPanel, 39 audio_patch_handle_t patchHandle, 40 audio_io_handle_t playbackThreadHandle, 41 audio_io_handle_t recordThreadHandle) 42 : mPatchPanel(patchPanel), 43 mPatchHandle(patchHandle), 44 mPlaybackThreadHandle(playbackThreadHandle), 45 mRecordThreadHandle(recordThreadHandle) {} 46 SoftwarePatch(const SoftwarePatch&) = default; 47 48 status_t getLatencyMs_l(double* latencyMs) const REQUIRES(audio_utils::AudioFlinger_Mutex); getPatchHandle()49 audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }; getPlaybackThreadHandle()50 audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; }; getRecordThreadHandle()51 audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; }; 52 53 private: 54 const sp<const IAfPatchPanel> mPatchPanel; 55 const audio_patch_handle_t mPatchHandle; 56 const audio_io_handle_t mPlaybackThreadHandle; 57 const audio_io_handle_t mRecordThreadHandle; 58 }; 59 60 class IAfPatchPanelCallback : public virtual RefBase { 61 public: 62 virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) REQUIRES(mutex()) = 0; 63 virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) REQUIRES(mutex()) = 0; 64 virtual IAfPlaybackThread* primaryPlaybackThread_l() const REQUIRES(mutex()) = 0; 65 virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const 66 REQUIRES(mutex()) = 0; 67 virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const 68 REQUIRES(mutex()) = 0; 69 virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const REQUIRES(mutex()) = 0; 70 virtual sp<IAfThreadBase> openInput_l(audio_module_handle_t module, 71 audio_io_handle_t* input, 72 audio_config_t* config, 73 audio_devices_t device, 74 const char* address, 75 audio_source_t source, 76 audio_input_flags_t flags, 77 audio_devices_t outputDevice, 78 const String8& outputDeviceAddress) REQUIRES(mutex()) = 0; 79 virtual sp<IAfThreadBase> openOutput_l(audio_module_handle_t module, 80 audio_io_handle_t* output, 81 audio_config_t* halConfig, 82 audio_config_base_t* mixerConfig, 83 audio_devices_t deviceType, 84 const String8& address, 85 audio_output_flags_t* flags, 86 audio_attributes_t attributes) REQUIRES(mutex()) = 0; 87 virtual audio_utils::mutex& mutex() const 88 RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0; 89 virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>& 90 getAudioHwDevs_l() const REQUIRES(mutex()) = 0; 91 virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0; 92 virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0; 93 virtual void updateDownStreamPatches_l( 94 const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams) 95 REQUIRES(mutex()) = 0; 96 virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) 97 REQUIRES(mutex()) = 0; 98 }; 99 100 class IAfPatchPanel : public virtual RefBase { 101 public: 102 static sp<IAfPatchPanel> create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback); 103 104 // Extraction of inner Endpoint and Patch classes would require interfaces 105 // (in the Endpoint case a templated interface) but that seems 106 // excessive for now. We keep them as inner classes until extraction 107 // is needed. 108 template <typename ThreadType, typename TrackType> 109 class Endpoint final { 110 public: 111 Endpoint() = default; 112 Endpoint(const Endpoint&) = delete; 113 Endpoint& operator=(const Endpoint& other) noexcept { 114 mThread = other.mThread; 115 mCloseThread = other.mCloseThread; 116 mHandle = other.mHandle; 117 mTrack = other.mTrack; 118 return *this; 119 } Endpoint(Endpoint && other)120 Endpoint(Endpoint&& other) noexcept { swap(other); } 121 Endpoint& operator=(Endpoint&& other) noexcept { 122 swap(other); 123 return *this; 124 } ~Endpoint()125 ~Endpoint() { 126 ALOGE_IF( 127 mHandle != AUDIO_PATCH_HANDLE_NONE, 128 "A non empty Patch Endpoint leaked, handle %d", mHandle); 129 } 130 checkTrack(TrackType * trackOrNull)131 status_t checkTrack(TrackType* trackOrNull) const { 132 if (trackOrNull == nullptr) return NO_MEMORY; 133 return trackOrNull->initCheck(); 134 } handle()135 audio_patch_handle_t handle() const { return mHandle; } thread()136 sp<ThreadType> thread() const { return mThread; } track()137 sp<TrackType> track() const { return mTrack; } const_thread()138 sp<const ThreadType> const_thread() const { return mThread; } const_track()139 sp<const TrackType> const_track() const { return mTrack; } 140 closeConnections_l(const sp<IAfPatchPanel> & panel)141 void closeConnections_l(const sp<IAfPatchPanel>& panel) 142 REQUIRES(audio_utils::AudioFlinger_Mutex) 143 NO_THREAD_SAFETY_ANALYSIS // this is broken in clang 144 { 145 if (mHandle != AUDIO_PATCH_HANDLE_NONE) { 146 panel->releaseAudioPatch_l(mHandle); 147 mHandle = AUDIO_PATCH_HANDLE_NONE; 148 } 149 if (mThread != nullptr) { 150 if (mTrack != nullptr) { 151 mThread->deletePatchTrack(mTrack); 152 } 153 if (mCloseThread) { 154 panel->closeThreadInternal_l(mThread); 155 } 156 } 157 } handlePtr()158 audio_patch_handle_t* handlePtr() { return &mHandle; } 159 void setThread(const sp<ThreadType>& thread, bool closeThread = true) { 160 mThread = thread; 161 mCloseThread = closeThread; 162 } 163 template <typename T> setTrackAndPeer(const sp<TrackType> & track,const sp<T> & peer,bool holdReference)164 void setTrackAndPeer(const sp<TrackType>& track, const sp<T>& peer, bool holdReference) { 165 mTrack = track; 166 mThread->addPatchTrack(mTrack); 167 mTrack->setPeerProxy(peer, holdReference); 168 mClearPeerProxy = holdReference; 169 } clearTrackPeer()170 void clearTrackPeer() { 171 if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy(); 172 } stopTrack()173 void stopTrack() { 174 if (mTrack) mTrack->stop(); 175 } 176 swap(Endpoint & other)177 void swap(Endpoint& other) noexcept { 178 using std::swap; 179 swap(mThread, other.mThread); 180 swap(mCloseThread, other.mCloseThread); 181 swap(mClearPeerProxy, other.mClearPeerProxy); 182 swap(mHandle, other.mHandle); 183 swap(mTrack, other.mTrack); 184 } 185 swap(Endpoint & a,Endpoint & b)186 friend void swap(Endpoint& a, Endpoint& b) noexcept { a.swap(b); } 187 188 private: 189 sp<ThreadType> mThread; 190 bool mCloseThread = true; 191 bool mClearPeerProxy = true; 192 audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE; 193 sp<TrackType> mTrack; 194 }; 195 196 class Patch final { 197 public: Patch(const struct audio_patch & patch,bool endpointPatch)198 Patch(const struct audio_patch& patch, bool endpointPatch) 199 : mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {} 200 Patch() = default; 201 ~Patch(); Patch(const Patch & other)202 Patch(const Patch& other) noexcept { 203 mAudioPatch = other.mAudioPatch; 204 mHalHandle = other.mHalHandle; 205 mPlayback = other.mPlayback; 206 mRecord = other.mRecord; 207 mThread = other.mThread; 208 mIsEndpointPatch = other.mIsEndpointPatch; 209 } Patch(Patch && other)210 Patch(Patch&& other) noexcept { swap(other); } 211 Patch& operator=(Patch&& other) noexcept { 212 swap(other); 213 return *this; 214 } 215 swap(Patch & other)216 void swap(Patch& other) noexcept { 217 using std::swap; 218 swap(mAudioPatch, other.mAudioPatch); 219 swap(mHalHandle, other.mHalHandle); 220 swap(mPlayback, other.mPlayback); 221 swap(mRecord, other.mRecord); 222 swap(mThread, other.mThread); 223 swap(mIsEndpointPatch, other.mIsEndpointPatch); 224 } 225 swap(Patch & a,Patch & b)226 friend void swap(Patch& a, Patch& b) noexcept { a.swap(b); } 227 228 status_t createConnections_l(const sp<IAfPatchPanel>& panel) 229 REQUIRES(audio_utils::AudioFlinger_Mutex); 230 void clearConnections_l(const sp<IAfPatchPanel>& panel) 231 REQUIRES(audio_utils::AudioFlinger_Mutex); isSoftware()232 bool isSoftware() const { 233 return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE || 234 mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; 235 } 236 setThread(const sp<IAfThreadBase> & thread)237 void setThread(const sp<IAfThreadBase>& thread) { mThread = thread; } thread()238 wp<IAfThreadBase> thread() const { return mThread; } 239 240 // returns the latency of the patch (from record to playback). 241 status_t getLatencyMs(double* latencyMs) const; 242 243 String8 dump(audio_patch_handle_t myHandle) const; 244 245 // Note that audio_patch::id is only unique within a HAL module 246 struct audio_patch mAudioPatch; 247 // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0 248 audio_patch_handle_t mHalHandle = AUDIO_PATCH_HANDLE_NONE; 249 // below members are used by a software audio patch connecting a source device from a 250 // given audio HW module to a sink device on an other audio HW module. 251 // the objects are created by createConnections() and released by clearConnections() 252 // playback thread is created if no existing playback thread can be used 253 // connects playback thread output to sink device 254 Endpoint<IAfPlaybackThread, IAfPatchTrack> mPlayback; 255 // connects source device to record thread input 256 Endpoint<IAfRecordThread, IAfPatchRecord> mRecord; 257 258 wp<IAfThreadBase> mThread; 259 bool mIsEndpointPatch; 260 }; 261 262 /* List connected audio ports and their attributes */ 263 virtual status_t listAudioPorts_l(unsigned int* num_ports, struct audio_port* ports) 264 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 265 266 /* Get supported attributes for a given audio port */ 267 virtual status_t getAudioPort_l(struct audio_port_v7* port) 268 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 269 270 /* Create a patch between several source and sink ports */ 271 virtual status_t createAudioPatch_l( 272 const struct audio_patch* patch, 273 audio_patch_handle_t* handle, 274 bool endpointPatch = false) 275 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 276 277 /* Release a patch */ 278 virtual status_t releaseAudioPatch_l(audio_patch_handle_t handle) 279 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 280 281 /* List connected audio devices and they attributes */ 282 virtual status_t listAudioPatches_l(unsigned int* num_patches, struct audio_patch* patches) 283 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 284 285 // Retrieves all currently estrablished software patches for a stream 286 // opened on an intermediate module. 287 virtual status_t getDownstreamSoftwarePatches( 288 audio_io_handle_t stream, std::vector<SoftwarePatch>* patches) const = 0; 289 290 // Notifies patch panel about all opened and closed streams. 291 virtual void notifyStreamOpened( 292 AudioHwDevice* audioHwDevice, audio_io_handle_t stream, struct audio_patch* patch) = 0; 293 294 virtual void notifyStreamClosed(audio_io_handle_t stream) = 0; 295 296 virtual void dump(int fd) const = 0; 297 298 virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const 299 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 300 301 virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const 302 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 303 304 virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const 305 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 306 307 /** 308 * Get the attributes of the mix port when connecting to the given device port. 309 */ 310 virtual status_t getAudioMixPort_l( 311 const struct audio_port_v7* devicePort, 312 struct audio_port_v7* mixPort) REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 313 }; 314 315 } // namespace android 316