blob: 15b6ddfed9f6fdceb334555f93294c867564774a [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,
Dean Wheatleydfb67b82024-01-23 09:36:29 +110085 audio_output_flags_t* flags,
Haofan Wangb75aa6a2024-07-09 23:06:58 -070086 audio_attributes_t attributes) REQUIRES(mutex()) = 0;
Andy Hung36346122023-08-31 15:24:24 -070087 virtual audio_utils::mutex& mutex() const
88 RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hung68631eb2023-07-17 14:36:08 -070089 virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
Andy Hung36346122023-08-31 15:24:24 -070090 getAudioHwDevs_l() const REQUIRES(mutex()) = 0;
Andy Hung68631eb2023-07-17 14:36:08 -070091 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(
Andy Hung36346122023-08-31 15:24:24 -070094 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;
Andy Hung68631eb2023-07-17 14:36:08 -070098};
99
Andy Hungd63e79d2023-07-13 16:52:46 -0700100class IAfPatchPanel : public virtual RefBase {
101public:
Andy Hung68631eb2023-07-17 14:36:08 -0700102 static sp<IAfPatchPanel> create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback);
Andy Hungd63e79d2023-07-13 16:52:46 -0700103
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 }
120 Endpoint(Endpoint&& other) noexcept { swap(other); }
121 Endpoint& operator=(Endpoint&& other) noexcept {
122 swap(other);
123 return *this;
124 }
125 ~Endpoint() {
126 ALOGE_IF(
127 mHandle != AUDIO_PATCH_HANDLE_NONE,
128 "A non empty Patch Endpoint leaked, handle %d", mHandle);
129 }
130
131 status_t checkTrack(TrackType* trackOrNull) const {
132 if (trackOrNull == nullptr) return NO_MEMORY;
133 return trackOrNull->initCheck();
134 }
135 audio_patch_handle_t handle() const { return mHandle; }
136 sp<ThreadType> thread() const { return mThread; }
137 sp<TrackType> track() const { return mTrack; }
138 sp<const ThreadType> const_thread() const { return mThread; }
139 sp<const TrackType> const_track() const { return mTrack; }
140
Andy Hung36346122023-08-31 15:24:24 -0700141 void closeConnections_l(const sp<IAfPatchPanel>& panel)
142 REQUIRES(audio_utils::AudioFlinger_Mutex)
143 NO_THREAD_SAFETY_ANALYSIS // this is broken in clang
144 {
Andy Hungd63e79d2023-07-13 16:52:46 -0700145 if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
Andy Hung36346122023-08-31 15:24:24 -0700146 panel->releaseAudioPatch_l(mHandle);
Andy Hungd63e79d2023-07-13 16:52:46 -0700147 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 }
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>
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 }
170 void clearTrackPeer() {
171 if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy();
172 }
173 void stopTrack() {
174 if (mTrack) mTrack->stop();
175 }
176
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
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:
198 Patch(const struct audio_patch& patch, bool endpointPatch)
199 : mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {}
200 Patch() = default;
201 ~Patch();
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 }
210 Patch(Patch&& other) noexcept { swap(other); }
211 Patch& operator=(Patch&& other) noexcept {
212 swap(other);
213 return *this;
214 }
215
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
226 friend void swap(Patch& a, Patch& b) noexcept { a.swap(b); }
227
Andy Hung36346122023-08-31 15:24:24 -0700228 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);
Andy Hungd63e79d2023-07-13 16:52:46 -0700232 bool isSoftware() const {
233 return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
234 mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE;
235 }
236
237 void setThread(const sp<IAfThreadBase>& thread) { mThread = 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 */
Andy Hung36346122023-08-31 15:24:24 -0700263 virtual status_t listAudioPorts_l(unsigned int* num_ports, struct audio_port* ports)
264 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700265
266 /* Get supported attributes for a given audio port */
Andy Hung36346122023-08-31 15:24:24 -0700267 virtual status_t getAudioPort_l(struct audio_port_v7* port)
268 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700269
270 /* Create a patch between several source and sink ports */
Andy Hung36346122023-08-31 15:24:24 -0700271 virtual status_t createAudioPatch_l(
Andy Hungd63e79d2023-07-13 16:52:46 -0700272 const struct audio_patch* patch,
273 audio_patch_handle_t* handle,
Andy Hung36346122023-08-31 15:24:24 -0700274 bool endpointPatch = false)
275 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700276
277 /* Release a patch */
Andy Hung36346122023-08-31 15:24:24 -0700278 virtual status_t releaseAudioPatch_l(audio_patch_handle_t handle)
279 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700280
281 /* List connected audio devices and they attributes */
Andy Hung36346122023-08-31 15:24:24 -0700282 virtual status_t listAudioPatches_l(unsigned int* num_patches, struct audio_patch* patches)
283 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700284
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
Andy Hung36346122023-08-31 15:24:24 -0700298 virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const
299 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700300
Andy Hung36346122023-08-31 15:24:24 -0700301 virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const
302 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
Andy Hungd63e79d2023-07-13 16:52:46 -0700303
Andy Hung36346122023-08-31 15:24:24 -0700304 virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
305 REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
jiabin12537fc2023-10-12 17:56:08 +0000306
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;
Andy Hungd63e79d2023-07-13 16:52:46 -0700313};
314
315} // namespace android