blob: 5d6bf00d85f1c7477cef0dac5b17d57d9e3a276f [file] [log] [blame]
Eric Laurent1c333e22014-05-20 10:48:17 -07001/*
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
Mikhail Naganovdea53042018-04-26 13:10:21 -070022// PatchPanel is concealed within AudioFlinger, their lifetimes are the same.
23class PatchPanel {
Eric Laurent1c333e22014-05-20 10:48:17 -070024public:
Mikhail Naganovdea53042018-04-26 13:10:21 -070025 explicit PatchPanel(AudioFlinger* audioFlinger) : mAudioFlinger(*audioFlinger) {}
Eric Laurent1c333e22014-05-20 10:48:17 -070026
27 /* List connected audio ports and their attributes */
28 status_t listAudioPorts(unsigned int *num_ports,
29 struct audio_port *ports);
30
31 /* Get supported attributes for a given audio port */
32 status_t getAudioPort(struct audio_port *port);
33
34 /* Create a patch between several source and sink ports */
35 status_t createAudioPatch(const struct audio_patch *patch,
36 audio_patch_handle_t *handle);
37
38 /* Release a patch */
39 status_t releaseAudioPatch(audio_patch_handle_t handle);
40
41 /* List connected audio devices and they attributes */
42 status_t listAudioPatches(unsigned int *num_patches,
43 struct audio_patch *patches);
44
Mikhail Naganov201369b2018-05-16 16:52:32 -070045 void dump(int fd);
46
Mikhail Naganovdea53042018-04-26 13:10:21 -070047private:
Mikhail Naganov444ecc32018-05-01 17:40:05 -070048 template<typename ThreadType, typename TrackType>
49 class Endpoint {
50 public:
Mikhail Naganov9dfa2642018-05-10 10:09:19 -070051 Endpoint() = default;
52 Endpoint(Endpoint&& other) { *this = std::move(other); }
53 Endpoint& operator=(Endpoint&& other) {
54 ALOGE_IF(mHandle != AUDIO_PATCH_HANDLE_NONE,
55 "A non empty Patch Endpoint leaked, handle %d", mHandle);
56 *this = other;
57 other.mHandle = AUDIO_PATCH_HANDLE_NONE;
58 return *this;
59 }
60
Mikhail Naganov444ecc32018-05-01 17:40:05 -070061 status_t checkTrack(TrackType *trackOrNull) const {
62 if (trackOrNull == nullptr) return NO_MEMORY;
63 return trackOrNull->initCheck();
64 }
65 audio_patch_handle_t handle() const { return mHandle; }
66 sp<ThreadType> thread() { return mThread; }
67 sp<TrackType> track() { return mTrack; }
Andy Hungc3ab7732018-06-01 13:46:29 -070068 sp<const TrackType> const_track() const { return mTrack; }
Mikhail Naganov444ecc32018-05-01 17:40:05 -070069
70 void closeConnections(PatchPanel *panel) {
71 if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
72 panel->releaseAudioPatch(mHandle);
73 mHandle = AUDIO_PATCH_HANDLE_NONE;
74 }
75 if (mThread != 0) {
76 if (mTrack != 0) {
77 mThread->deletePatchTrack(mTrack);
78 }
79 if (mCloseThread) {
80 panel->mAudioFlinger.closeThreadInternal_l(mThread);
81 }
82 }
83 }
84 audio_patch_handle_t* handlePtr() { return &mHandle; }
85 void setThread(const sp<ThreadType>& thread, bool closeThread = true) {
86 mThread = thread;
87 mCloseThread = closeThread;
88 }
89 void setTrackAndPeer(const sp<TrackType>& track,
90 ThreadBase::PatchProxyBufferProvider *peer) {
91 mTrack = track;
92 mThread->addPatchTrack(mTrack);
93 mTrack->setPeerProxy(peer);
94 }
95 void stopTrack() { if (mTrack) mTrack->stop(); }
96
97 private:
Mikhail Naganov9dfa2642018-05-10 10:09:19 -070098 Endpoint(const Endpoint&) = default;
99 Endpoint& operator=(const Endpoint&) = default;
100
Mikhail Naganov444ecc32018-05-01 17:40:05 -0700101 sp<ThreadType> mThread;
102 bool mCloseThread = true;
103 audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE;
104 sp<TrackType> mTrack;
105 };
106
Eric Laurent1c333e22014-05-20 10:48:17 -0700107 class Patch {
108 public:
Mikhail Naganovdea53042018-04-26 13:10:21 -0700109 explicit Patch(const struct audio_patch &patch) : mAudioPatch(patch) {}
Mikhail Naganov444ecc32018-05-01 17:40:05 -0700110 ~Patch();
Mikhail Naganov9dfa2642018-05-10 10:09:19 -0700111 Patch(const Patch&) = delete;
112 Patch(Patch&&) = default;
113 Patch& operator=(const Patch&) = delete;
114 Patch& operator=(Patch&&) = default;
Eric Laurent1c333e22014-05-20 10:48:17 -0700115
Mikhail Naganovdea53042018-04-26 13:10:21 -0700116 status_t createConnections(PatchPanel *panel);
117 void clearConnections(PatchPanel *panel);
Mikhail Naganov444ecc32018-05-01 17:40:05 -0700118 bool isSoftware() const {
119 return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
120 mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; }
Mikhail Naganovdea53042018-04-26 13:10:21 -0700121
Andy Hungc3ab7732018-06-01 13:46:29 -0700122 // returns the latency of the patch (from record to playback).
123 status_t getLatencyMs(double *latencyMs) const;
124
Mikhail Naganov201369b2018-05-16 16:52:32 -0700125 String8 dump(audio_patch_handle_t myHandle);
126
Mikhail Naganovdea53042018-04-26 13:10:21 -0700127 // Note that audio_patch::id is only unique within a HAL module
Eric Laurent83b88082014-06-20 18:31:16 -0700128 struct audio_patch mAudioPatch;
Eric Laurentb997d3a2016-06-07 18:23:45 -0700129 // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0
Mikhail Naganovdea53042018-04-26 13:10:21 -0700130 audio_patch_handle_t mHalHandle = AUDIO_PATCH_HANDLE_NONE;
Eric Laurentb997d3a2016-06-07 18:23:45 -0700131 // below members are used by a software audio patch connecting a source device from a
132 // given audio HW module to a sink device on an other audio HW module.
Mikhail Naganovdea53042018-04-26 13:10:21 -0700133 // the objects are created by createConnections() and released by clearConnections()
134 // playback thread is created if no existing playback thread can be used
Mikhail Naganov444ecc32018-05-01 17:40:05 -0700135 // connects playback thread output to sink device
136 Endpoint<PlaybackThread, PlaybackThread::PatchTrack> mPlayback;
137 // connects source device to record thread input
138 Endpoint<RecordThread, RecordThread::PatchRecord> mRecord;
Eric Laurent1c333e22014-05-20 10:48:17 -0700139 };
Eric Laurent83b88082014-06-20 18:31:16 -0700140
Mikhail Naganov444ecc32018-05-01 17:40:05 -0700141 sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
142
Mikhail Naganovdea53042018-04-26 13:10:21 -0700143 AudioFlinger &mAudioFlinger;
144 std::map<audio_patch_handle_t, Patch> mPatches;
Eric Laurent1c333e22014-05-20 10:48:17 -0700145};