blob: 6110e4ccb1c9b2a2c2fd91c59a0ba12fd0ac3b95 [file] [log] [blame]
Andy Hungd63e79d2023-07-13 16:52:46 -07001/*
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
Andy Hung57091702023-07-18 18:31:50 -070019// 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
Andy Hungd63e79d2023-07-13 16:52:46 -070030namespace android {
31
32class IAfPatchPanel;
Andy Hung68631eb2023-07-17 14:36:08 -070033class PatchCommandThread;
Andy Hungd63e79d2023-07-13 16:52:46 -070034
35class SoftwarePatch {
36public:
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
Andy Hung36346122023-08-31 15:24:24 -070048 status_t getLatencyMs_l(double* latencyMs) const REQUIRES(audio_utils::AudioFlinger_Mutex);
Andy Hungd63e79d2023-07-13 16:52:46 -070049 audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
50 audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
51 audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
52
53private:
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
Andy Hung68631eb2023-07-17 14:36:08 -070060class IAfPatchPanelCallback : public virtual RefBase {
61public:
Andy Hung36346122023-08-31 15:24:24 -070062 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;
Andy Hung68631eb2023-07-17 14:36:08 -070070 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,
Andy Hung36346122023-08-31 15:24:24 -070078 const String8& outputDeviceAddress) REQUIRES(mutex()) = 0;
Andy Hung68631eb2023-07-17 14:36:08 -070079 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,
Andy Hung36346122023-08-31 15:24:24 -070085 audio_output_flags_t flags) REQUIRES(mutex()) = 0;
86 virtual audio_utils::mutex& mutex() const
87 RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hung68631eb2023-07-17 14:36:08 -070088 virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
Andy Hung36346122023-08-31 15:24:24 -070089 getAudioHwDevs_l() const REQUIRES(mutex()) = 0;
Andy Hung68631eb2023-07-17 14:36:08 -070090 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(
Andy Hung36346122023-08-31 15:24:24 -070093 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;
Andy Hung68631eb2023-07-17 14:36:08 -070097};
98
Andy Hungd63e79d2023-07-13 16:52:46 -070099class IAfPatchPanel : public virtual RefBase {
100public:
Andy Hung68631eb2023-07-17 14:36:08 -0700101 static sp<IAfPatchPanel> create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback);
Andy Hungd63e79d2023-07-13 16:52:46 -0700102
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 }
119 Endpoint(Endpoint&& other) noexcept { swap(other); }
120 Endpoint& operator=(Endpoint&& other) noexcept {
121 swap(other);
122 return *this;
123 }
124 ~Endpoint() {
125 ALOGE_IF(
126 mHandle != AUDIO_PATCH_HANDLE_NONE,
127 "A non empty Patch Endpoint leaked, handle %d", mHandle);
128 }
129
130 status_t checkTrack(TrackType* trackOrNull) const {
131 if (trackOrNull == nullptr) return NO_MEMORY;
132 return trackOrNull->initCheck();
133 }
134 audio_patch_handle_t handle() const { return mHandle; }
135 sp<ThreadType> thread() const { return mThread; }
136 sp<TrackType> track() const { return mTrack; }
137 sp<const ThreadType> const_thread() const { return mThread; }
138 sp<const TrackType> const_track() const { return mTrack; }
139
Andy Hung36346122023-08-31 15:24:24 -0700140 void closeConnections_l(const sp<IAfPatchPanel>& panel)
141 REQUIRES(audio_utils::AudioFlinger_Mutex)
142 NO_THREAD_SAFETY_ANALYSIS // this is broken in clang
143 {
Andy Hungd63e79d2023-07-13 16:52:46 -0700144 if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
Andy Hung36346122023-08-31 15:24:24 -0700145 panel->releaseAudioPatch_l(mHandle);
Andy Hungd63e79d2023-07-13 16:52:46 -0700146 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 }
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>
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 }
169 void clearTrackPeer() {
170 if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy();
171 }
172 void stopTrack() {
173 if (mTrack) mTrack->stop();
174 }
175
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
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:
197 Patch(const struct audio_patch& patch, bool endpointPatch)
198 : mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {}
199 Patch() = default;
200 ~Patch();
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 }
209 Patch(Patch&& other) noexcept { swap(other); }
210 Patch& operator=(Patch&& other) noexcept {
211 swap(other);
212 return *this;
213 }
214
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
225 friend void swap(Patch& a, Patch& b) noexcept { a.swap(b); }
226
Andy Hung36346122023-08-31 15:24:24 -0700227 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);
Andy Hungd63e79d2023-07-13 16:52:46 -0700231 bool isSoftware() const {
232 return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
233 mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE;
234 }
235
236 void setThread(const sp<IAfThreadBase>& thread) { mThread = 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 */
Andy Hung36346122023-08-31 15:24:24 -0700262 virtual status_t listAudioPorts_l(unsigned int* num_ports, struct audio_port* ports)
263 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700264
265 /* Get supported attributes for a given audio port */
Andy Hung36346122023-08-31 15:24:24 -0700266 virtual status_t getAudioPort_l(struct audio_port_v7* port)
267 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700268
269 /* Create a patch between several source and sink ports */
Andy Hung36346122023-08-31 15:24:24 -0700270 virtual status_t createAudioPatch_l(
Andy Hungd63e79d2023-07-13 16:52:46 -0700271 const struct audio_patch* patch,
272 audio_patch_handle_t* handle,
Andy Hung36346122023-08-31 15:24:24 -0700273 bool endpointPatch = false)
274 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700275
276 /* Release a patch */
Andy Hung36346122023-08-31 15:24:24 -0700277 virtual status_t releaseAudioPatch_l(audio_patch_handle_t handle)
278 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700279
280 /* List connected audio devices and they attributes */
Andy Hung36346122023-08-31 15:24:24 -0700281 virtual status_t listAudioPatches_l(unsigned int* num_patches, struct audio_patch* patches)
282 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700283
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
Andy Hung36346122023-08-31 15:24:24 -0700297 virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const
298 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700299
Andy Hung36346122023-08-31 15:24:24 -0700300 virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const
301 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700302
Andy Hung36346122023-08-31 15:24:24 -0700303 virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
304 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
jiabin12537fc2023-10-12 17:56:08 +0000305
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;
Andy Hungd63e79d2023-07-13 16:52:46 -0700312};
313
314} // namespace android