xref: /aosp_15_r20/frameworks/av/services/audioflinger/PatchPanel.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker **
3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2014, The Android Open Source Project
4*ec779b8eSAndroid Build Coastguard Worker **
5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*ec779b8eSAndroid Build Coastguard Worker **
9*ec779b8eSAndroid Build Coastguard Worker **     http://www.apache.org/licenses/LICENSE-2.0
10*ec779b8eSAndroid Build Coastguard Worker **
11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License.
16*ec779b8eSAndroid Build Coastguard Worker */
17*ec779b8eSAndroid Build Coastguard Worker 
18*ec779b8eSAndroid Build Coastguard Worker #pragma once
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker #include "IAfPatchPanel.h"
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker #include <map>  // avoid transitive dependency
23*ec779b8eSAndroid Build Coastguard Worker #include <set>  // avoid transitive dependency
24*ec779b8eSAndroid Build Coastguard Worker 
25*ec779b8eSAndroid Build Coastguard Worker namespace android {
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker class PatchPanel : public IAfPatchPanel {
28*ec779b8eSAndroid Build Coastguard Worker public:
PatchPanel(const sp<IAfPatchPanelCallback> & afPatchPanelCallback)29*ec779b8eSAndroid Build Coastguard Worker     explicit PatchPanel(const sp<IAfPatchPanelCallback>& afPatchPanelCallback)
30*ec779b8eSAndroid Build Coastguard Worker         : mAfPatchPanelCallback(afPatchPanelCallback) {}
31*ec779b8eSAndroid Build Coastguard Worker 
32*ec779b8eSAndroid Build Coastguard Worker     /* List connected audio ports and their attributes */
33*ec779b8eSAndroid Build Coastguard Worker     status_t listAudioPorts_l(unsigned int *num_ports,
34*ec779b8eSAndroid Build Coastguard Worker             struct audio_port* ports) final REQUIRES(audio_utils::AudioFlinger_Mutex);
35*ec779b8eSAndroid Build Coastguard Worker 
36*ec779b8eSAndroid Build Coastguard Worker     /* Get supported attributes for a given audio port */
37*ec779b8eSAndroid Build Coastguard Worker     status_t getAudioPort_l(struct audio_port_v7* port) final
38*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
39*ec779b8eSAndroid Build Coastguard Worker 
40*ec779b8eSAndroid Build Coastguard Worker     /* Create a patch between several source and sink ports */
41*ec779b8eSAndroid Build Coastguard Worker     status_t createAudioPatch_l(const struct audio_patch *patch,
42*ec779b8eSAndroid Build Coastguard Worker                               audio_patch_handle_t *handle,
43*ec779b8eSAndroid Build Coastguard Worker                               bool endpointPatch = false) final
44*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
45*ec779b8eSAndroid Build Coastguard Worker 
46*ec779b8eSAndroid Build Coastguard Worker     /* Release a patch */
47*ec779b8eSAndroid Build Coastguard Worker     status_t releaseAudioPatch_l(audio_patch_handle_t handle) final
48*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
49*ec779b8eSAndroid Build Coastguard Worker 
50*ec779b8eSAndroid Build Coastguard Worker     /* List connected audio devices and they attributes */
51*ec779b8eSAndroid Build Coastguard Worker     status_t listAudioPatches_l(unsigned int *num_patches,
52*ec779b8eSAndroid Build Coastguard Worker             struct audio_patch* patches) final
53*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
54*ec779b8eSAndroid Build Coastguard Worker 
55*ec779b8eSAndroid Build Coastguard Worker     // Retrieves all currently established software patches for a stream
56*ec779b8eSAndroid Build Coastguard Worker     // opened on an intermediate module.
57*ec779b8eSAndroid Build Coastguard Worker     status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
58*ec779b8eSAndroid Build Coastguard Worker             std::vector<SoftwarePatch>* patches) const final;
59*ec779b8eSAndroid Build Coastguard Worker 
60*ec779b8eSAndroid Build Coastguard Worker     // Notifies patch panel about all opened and closed streams.
61*ec779b8eSAndroid Build Coastguard Worker     void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
62*ec779b8eSAndroid Build Coastguard Worker                             struct audio_patch* patch) final;
63*ec779b8eSAndroid Build Coastguard Worker     void notifyStreamClosed(audio_io_handle_t stream) final;
64*ec779b8eSAndroid Build Coastguard Worker 
65*ec779b8eSAndroid Build Coastguard Worker     void dump(int fd) const final;
66*ec779b8eSAndroid Build Coastguard Worker 
patches_l()67*ec779b8eSAndroid Build Coastguard Worker     const std::map<audio_patch_handle_t, Patch>& patches_l() const final
68*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex) { return mPatches; }
69*ec779b8eSAndroid Build Coastguard Worker 
70*ec779b8eSAndroid Build Coastguard Worker     status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final
71*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
72*ec779b8eSAndroid Build Coastguard Worker 
73*ec779b8eSAndroid Build Coastguard Worker     void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final
74*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
75*ec779b8eSAndroid Build Coastguard Worker 
76*ec779b8eSAndroid Build Coastguard Worker     /**
77*ec779b8eSAndroid Build Coastguard Worker      * Get the attributes of the mix port when connecting to the given device port
78*ec779b8eSAndroid Build Coastguard Worker      */
79*ec779b8eSAndroid Build Coastguard Worker     status_t getAudioMixPort_l(const audio_port_v7* devicePort, audio_port_v7* mixPort) final
80*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
81*ec779b8eSAndroid Build Coastguard Worker 
82*ec779b8eSAndroid Build Coastguard Worker private:
83*ec779b8eSAndroid Build Coastguard Worker     AudioHwDevice* findAudioHwDeviceByModule_l(audio_module_handle_t module)
84*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
85*ec779b8eSAndroid Build Coastguard Worker     sp<DeviceHalInterface> findHwDeviceByModule_l(audio_module_handle_t module)
86*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
87*ec779b8eSAndroid Build Coastguard Worker     void addSoftwarePatchToInsertedModules_l(
88*ec779b8eSAndroid Build Coastguard Worker             audio_module_handle_t module, audio_patch_handle_t handle,
89*ec779b8eSAndroid Build Coastguard Worker             const struct audio_patch *patch)
90*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(audio_utils::AudioFlinger_Mutex);
91*ec779b8eSAndroid Build Coastguard Worker     void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
92*ec779b8eSAndroid Build Coastguard Worker     /**
93*ec779b8eSAndroid Build Coastguard Worker      * erase the patch referred by its handle.
94*ec779b8eSAndroid Build Coastguard Worker      * @param handle of the patch to be erased
95*ec779b8eSAndroid Build Coastguard Worker      * @param reuseExistingHalPatch if set, do not trig the callback of listeners, listener
96*ec779b8eSAndroid Build Coastguard Worker      * would receive instead a onUpdateAudioPatch when the patch will be recreated.
97*ec779b8eSAndroid Build Coastguard Worker      * It prevents for example DeviceEffectManager to spuriously remove / add a device on an already
98*ec779b8eSAndroid Build Coastguard Worker      * opened input / output mix.
99*ec779b8eSAndroid Build Coastguard Worker      */
100*ec779b8eSAndroid Build Coastguard Worker     void erasePatch(audio_patch_handle_t handle, bool reuseExistingHalPatch = false);
101*ec779b8eSAndroid Build Coastguard Worker 
102*ec779b8eSAndroid Build Coastguard Worker     /**
103*ec779b8eSAndroid Build Coastguard Worker      * Returns true if the old and new patches passed as arguments describe the same
104*ec779b8eSAndroid Build Coastguard Worker      * connections between the first sink and the first source
105*ec779b8eSAndroid Build Coastguard Worker      * @param oldPatch previous patch
106*ec779b8eSAndroid Build Coastguard Worker      * @param newPatch new patch
107*ec779b8eSAndroid Build Coastguard Worker      * @return true if the route is unchanged between the old and new patch, false otherwise
108*ec779b8eSAndroid Build Coastguard Worker      */
patchesHaveSameRoute(const struct audio_patch & newPatch,const struct audio_patch & oldPatch)109*ec779b8eSAndroid Build Coastguard Worker     inline bool patchesHaveSameRoute(
110*ec779b8eSAndroid Build Coastguard Worker             const struct audio_patch &newPatch, const struct audio_patch &oldPatch) const {
111*ec779b8eSAndroid Build Coastguard Worker         return (newPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
112*ec779b8eSAndroid Build Coastguard Worker                 oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
113*ec779b8eSAndroid Build Coastguard Worker                 newPatch.sources[0].id == oldPatch.sources[0].id &&
114*ec779b8eSAndroid Build Coastguard Worker                 newPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
115*ec779b8eSAndroid Build Coastguard Worker                 oldPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
116*ec779b8eSAndroid Build Coastguard Worker                 newPatch.sinks[0].ext.mix.handle == oldPatch.sinks[0].ext.mix.handle) ||
117*ec779b8eSAndroid Build Coastguard Worker                 (newPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
118*ec779b8eSAndroid Build Coastguard Worker                 oldPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
119*ec779b8eSAndroid Build Coastguard Worker                 newPatch.sinks[0].id == oldPatch.sinks[0].id &&
120*ec779b8eSAndroid Build Coastguard Worker                 newPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
121*ec779b8eSAndroid Build Coastguard Worker                 oldPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
122*ec779b8eSAndroid Build Coastguard Worker                 newPatch.sources[0].ext.mix.handle == oldPatch.sources[0].ext.mix.handle);
123*ec779b8eSAndroid Build Coastguard Worker     }
124*ec779b8eSAndroid Build Coastguard Worker 
125*ec779b8eSAndroid Build Coastguard Worker     const sp<IAfPatchPanelCallback> mAfPatchPanelCallback;
126*ec779b8eSAndroid Build Coastguard Worker     std::map<audio_patch_handle_t, Patch> mPatches;
127*ec779b8eSAndroid Build Coastguard Worker 
128*ec779b8eSAndroid Build Coastguard Worker     // This map allows going from a thread to "downstream" software patches
129*ec779b8eSAndroid Build Coastguard Worker     // when a processing module inserted in between. Example:
130*ec779b8eSAndroid Build Coastguard Worker     //
131*ec779b8eSAndroid Build Coastguard Worker     //  from map value.streams                               map key
132*ec779b8eSAndroid Build Coastguard Worker     //  [Mixer thread] --> [Virtual output device] --> [Processing module] ---\
133*ec779b8eSAndroid Build Coastguard Worker     //       [Harware module] <-- [Physical output device] <-- [S/W Patch] <--/
134*ec779b8eSAndroid Build Coastguard Worker     //                                                 from map value.sw_patches
135*ec779b8eSAndroid Build Coastguard Worker     //
136*ec779b8eSAndroid Build Coastguard Worker     // This allows the mixer thread to look up the threads of the software patch
137*ec779b8eSAndroid Build Coastguard Worker     // for propagating timing info, parameters, etc.
138*ec779b8eSAndroid Build Coastguard Worker     //
139*ec779b8eSAndroid Build Coastguard Worker     // The current assumptions are:
140*ec779b8eSAndroid Build Coastguard Worker     //   1) The processing module acts as a mixer with several outputs which
141*ec779b8eSAndroid Build Coastguard Worker     //      represent differently downmixed and / or encoded versions of the same
142*ec779b8eSAndroid Build Coastguard Worker     //      mixed stream. There is no 1:1 correspondence between the input streams
143*ec779b8eSAndroid Build Coastguard Worker     //      and the software patches, but rather a N:N correspondence between
144*ec779b8eSAndroid Build Coastguard Worker     //      a group of streams and a group of patches.
145*ec779b8eSAndroid Build Coastguard Worker     //   2) There are only a couple of inserted processing modules in the system,
146*ec779b8eSAndroid Build Coastguard Worker     //      so when looking for a stream or patch handle we can iterate over
147*ec779b8eSAndroid Build Coastguard Worker     //      all modules.
148*ec779b8eSAndroid Build Coastguard Worker     struct ModuleConnections {
149*ec779b8eSAndroid Build Coastguard Worker         std::set<audio_io_handle_t> streams;
150*ec779b8eSAndroid Build Coastguard Worker         std::set<audio_patch_handle_t> sw_patches;
151*ec779b8eSAndroid Build Coastguard Worker     };
152*ec779b8eSAndroid Build Coastguard Worker     std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
153*ec779b8eSAndroid Build Coastguard Worker };
154*ec779b8eSAndroid Build Coastguard Worker 
155*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
156