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) REQUIRES(mutex()) = 0; 86 virtual audio_utils::mutex& mutex() const 87 RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0; 88 virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>& 89 getAudioHwDevs_l() const REQUIRES(mutex()) = 0; 90 virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0; 91 virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0; 92 virtual void updateDownStreamPatches_l( 93 const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams) 94 REQUIRES(mutex()) = 0; 95 virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) 96 REQUIRES(mutex()) = 0; 97 }; 98 99 class IAfPatchPanel : public virtual RefBase { 100 public: 101 static sp<IAfPatchPanel> create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback); 102 103 // Extraction of inner Endpoint and Patch classes would require interfaces 104 // (in the Endpoint case a templated interface) but that seems 105 // excessive for now. We keep them as inner classes until extraction 106 // is needed. 107 template <typename ThreadType, typename TrackType> 108 class Endpoint final { 109 public: 110 Endpoint() = default; 111 Endpoint(const Endpoint&) = delete; 112 Endpoint& operator=(const Endpoint& other) noexcept { 113 mThread = other.mThread; 114 mCloseThread = other.mCloseThread; 115 mHandle = other.mHandle; 116 mTrack = other.mTrack; 117 return *this; 118 } Endpoint(Endpoint && other)119 Endpoint(Endpoint&& other) noexcept { swap(other); } 120 Endpoint& operator=(Endpoint&& other) noexcept { 121 swap(other); 122 return *this; 123 } ~Endpoint()124 ~Endpoint() { 125 ALOGE_IF( 126 mHandle != AUDIO_PATCH_HANDLE_NONE, 127 "A non empty Patch Endpoint leaked, handle %d", mHandle); 128 } 129 checkTrack(TrackType * trackOrNull)130 status_t checkTrack(TrackType* trackOrNull) const { 131 if (trackOrNull == nullptr) return NO_MEMORY; 132 return trackOrNull->initCheck(); 133 } handle()134 audio_patch_handle_t handle() const { return mHandle; } thread()135 sp<ThreadType> thread() const { return mThread; } track()136 sp<TrackType> track() const { return mTrack; } const_thread()137 sp<const ThreadType> const_thread() const { return mThread; } const_track()138 sp<const TrackType> const_track() const { return mTrack; } 139 closeConnections_l(const sp<IAfPatchPanel> & panel)140 void closeConnections_l(const sp<IAfPatchPanel>& panel) 141 REQUIRES(audio_utils::AudioFlinger_Mutex) 142 NO_THREAD_SAFETY_ANALYSIS // this is broken in clang 143 { 144 if (mHandle != AUDIO_PATCH_HANDLE_NONE) { 145 panel->releaseAudioPatch_l(mHandle); 146 mHandle = AUDIO_PATCH_HANDLE_NONE; 147 } 148 if (mThread != nullptr) { 149 if (mTrack != nullptr) { 150 mThread->deletePatchTrack(mTrack); 151 } 152 if (mCloseThread) { 153 panel->closeThreadInternal_l(mThread); 154 } 155 } 156 } handlePtr()157 audio_patch_handle_t* handlePtr() { return &mHandle; } 158 void setThread(const sp<ThreadType>& thread, bool closeThread = true) { 159 mThread = thread; 160 mCloseThread = closeThread; 161 } 162 template <typename T> setTrackAndPeer(const sp<TrackType> & track,const sp<T> & peer,bool holdReference)163 void setTrackAndPeer(const sp<TrackType>& track, const sp<T>& peer, bool holdReference) { 164 mTrack = track; 165 mThread->addPatchTrack(mTrack); 166 mTrack->setPeerProxy(peer, holdReference); 167 mClearPeerProxy = holdReference; 168 } clearTrackPeer()169 void clearTrackPeer() { 170 if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy(); 171 } stopTrack()172 void stopTrack() { 173 if (mTrack) mTrack->stop(); 174 } 175 swap(Endpoint & other)176 void swap(Endpoint& other) noexcept { 177 using std::swap; 178 swap(mThread, other.mThread); 179 swap(mCloseThread, other.mCloseThread); 180 swap(mClearPeerProxy, other.mClearPeerProxy); 181 swap(mHandle, other.mHandle); 182 swap(mTrack, other.mTrack); 183 } 184 swap(Endpoint & a,Endpoint & b)185 friend void swap(Endpoint& a, Endpoint& b) noexcept { a.swap(b); } 186 187 private: 188 sp<ThreadType> mThread; 189 bool mCloseThread = true; 190 bool mClearPeerProxy = true; 191 audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE; 192 sp<TrackType> mTrack; 193 }; 194 195 class Patch final { 196 public: Patch(const struct audio_patch & patch,bool endpointPatch)197 Patch(const struct audio_patch& patch, bool endpointPatch) 198 : mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {} 199 Patch() = default; 200 ~Patch(); Patch(const Patch & other)201 Patch(const Patch& other) noexcept { 202 mAudioPatch = other.mAudioPatch; 203 mHalHandle = other.mHalHandle; 204 mPlayback = other.mPlayback; 205 mRecord = other.mRecord; 206 mThread = other.mThread; 207 mIsEndpointPatch = other.mIsEndpointPatch; 208 } Patch(Patch && other)209 Patch(Patch&& other) noexcept { swap(other); } 210 Patch& operator=(Patch&& other) noexcept { 211 swap(other); 212 return *this; 213 } 214 swap(Patch & other)215 void swap(Patch& other) noexcept { 216 using std::swap; 217 swap(mAudioPatch, other.mAudioPatch); 218 swap(mHalHandle, other.mHalHandle); 219 swap(mPlayback, other.mPlayback); 220 swap(mRecord, other.mRecord); 221 swap(mThread, other.mThread); 222 swap(mIsEndpointPatch, other.mIsEndpointPatch); 223 } 224 swap(Patch & a,Patch & b)225 friend void swap(Patch& a, Patch& b) noexcept { a.swap(b); } 226 227 status_t createConnections_l(const sp<IAfPatchPanel>& panel) 228 REQUIRES(audio_utils::AudioFlinger_Mutex); 229 void clearConnections_l(const sp<IAfPatchPanel>& panel) 230 REQUIRES(audio_utils::AudioFlinger_Mutex); isSoftware()231 bool isSoftware() const { 232 return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE || 233 mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; 234 } 235 setThread(const sp<IAfThreadBase> & thread)236 void setThread(const sp<IAfThreadBase>& thread) { mThread = thread; } thread()237 wp<IAfThreadBase> thread() const { return mThread; } 238 239 // returns the latency of the patch (from record to playback). 240 status_t getLatencyMs(double* latencyMs) const; 241 242 String8 dump(audio_patch_handle_t myHandle) const; 243 244 // Note that audio_patch::id is only unique within a HAL module 245 struct audio_patch mAudioPatch; 246 // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0 247 audio_patch_handle_t mHalHandle = AUDIO_PATCH_HANDLE_NONE; 248 // below members are used by a software audio patch connecting a source device from a 249 // given audio HW module to a sink device on an other audio HW module. 250 // the objects are created by createConnections() and released by clearConnections() 251 // playback thread is created if no existing playback thread can be used 252 // connects playback thread output to sink device 253 Endpoint<IAfPlaybackThread, IAfPatchTrack> mPlayback; 254 // connects source device to record thread input 255 Endpoint<IAfRecordThread, IAfPatchRecord> mRecord; 256 257 wp<IAfThreadBase> mThread; 258 bool mIsEndpointPatch; 259 }; 260 261 /* List connected audio ports and their attributes */ 262 virtual status_t listAudioPorts_l(unsigned int* num_ports, struct audio_port* ports) 263 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 264 265 /* Get supported attributes for a given audio port */ 266 virtual status_t getAudioPort_l(struct audio_port_v7* port) 267 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 268 269 /* Create a patch between several source and sink ports */ 270 virtual status_t createAudioPatch_l( 271 const struct audio_patch* patch, 272 audio_patch_handle_t* handle, 273 bool endpointPatch = false) 274 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 275 276 /* Release a patch */ 277 virtual status_t releaseAudioPatch_l(audio_patch_handle_t handle) 278 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 279 280 /* List connected audio devices and they attributes */ 281 virtual status_t listAudioPatches_l(unsigned int* num_patches, struct audio_patch* patches) 282 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 283 284 // Retrieves all currently estrablished software patches for a stream 285 // opened on an intermediate module. 286 virtual status_t getDownstreamSoftwarePatches( 287 audio_io_handle_t stream, std::vector<SoftwarePatch>* patches) const = 0; 288 289 // Notifies patch panel about all opened and closed streams. 290 virtual void notifyStreamOpened( 291 AudioHwDevice* audioHwDevice, audio_io_handle_t stream, struct audio_patch* patch) = 0; 292 293 virtual void notifyStreamClosed(audio_io_handle_t stream) = 0; 294 295 virtual void dump(int fd) const = 0; 296 297 virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const 298 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 299 300 virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const 301 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 302 303 virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const 304 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 305 306 /** 307 * Get the attributes of the mix port when connecting to the given device port. 308 */ 309 virtual status_t getAudioMixPort_l( 310 const struct audio_port_v7* devicePort, 311 struct audio_port_v7* mixPort) REQUIRES(audio_utils::AudioFlinger_Mutex) = 0; 312 }; 313 314 } // namespace android 315