blob: b3c8a118754dfe6c90823de0f00d37d492d8a113 [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
Andy Hung6ac17eb2023-06-20 18:56:17 -070022public: // TODO(b/288339104) extract out of AudioFlinger class
Mikhail Naganovdea53042018-04-26 13:10:21 -070023// PatchPanel is concealed within AudioFlinger, their lifetimes are the same.
Andy Hungb6692eb2023-07-13 16:52:46 -070024class PatchPanel : public IAfPatchPanel {
Eric Laurent1c333e22014-05-20 10:48:17 -070025public:
Mikhail Naganovdea53042018-04-26 13:10:21 -070026 explicit PatchPanel(AudioFlinger* audioFlinger) : mAudioFlinger(*audioFlinger) {}
Eric Laurent1c333e22014-05-20 10:48:17 -070027
28 /* List connected audio ports and their attributes */
29 status_t listAudioPorts(unsigned int *num_ports,
Andy Hungb6692eb2023-07-13 16:52:46 -070030 struct audio_port* ports) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070031
32 /* Get supported attributes for a given audio port */
Andy Hungb6692eb2023-07-13 16:52:46 -070033 status_t getAudioPort(struct audio_port_v7* port) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070034
35 /* Create a patch between several source and sink ports */
36 status_t createAudioPatch(const struct audio_patch *patch,
Francois Gaffiee0dc36d2021-04-01 16:01:00 +020037 audio_patch_handle_t *handle,
Andy Hungb6692eb2023-07-13 16:52:46 -070038 bool endpointPatch = false) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070039
40 /* Release a patch */
Andy Hungb6692eb2023-07-13 16:52:46 -070041 status_t releaseAudioPatch(audio_patch_handle_t handle) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070042
43 /* List connected audio devices and they attributes */
44 status_t listAudioPatches(unsigned int *num_patches,
Andy Hungb6692eb2023-07-13 16:52:46 -070045 struct audio_patch* patches) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070046
Mikhail Naganovadca70f2018-07-09 12:49:25 -070047 // Retrieves all currently estrablished software patches for a stream
48 // opened on an intermediate module.
49 status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
Andy Hungb6692eb2023-07-13 16:52:46 -070050 std::vector<SoftwarePatch>* patches) const final;
Mikhail Naganovadca70f2018-07-09 12:49:25 -070051
52 // Notifies patch panel about all opened and closed streams.
Eric Laurent74c38dc2020-12-23 18:19:44 +010053 void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
Andy Hungb6692eb2023-07-13 16:52:46 -070054 struct audio_patch* patch) final;
55 void notifyStreamClosed(audio_io_handle_t stream) final;
Mikhail Naganovadca70f2018-07-09 12:49:25 -070056
Andy Hungb6692eb2023-07-13 16:52:46 -070057 void dump(int fd) const final;
Eric Laurent83b88082014-06-20 18:31:16 -070058
Eric Laurent9b2064c2019-11-22 17:25:04 -080059 // Call with AudioFlinger mLock held
Andy Hungb6692eb2023-07-13 16:52:46 -070060 const std::map<audio_patch_handle_t, Patch>& patches_l() const final { return mPatches; }
61
62 // Must be called under AudioFlinger::mLock
63 status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final;
64
65 void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final;
Eric Laurent9b2064c2019-11-22 17:25:04 -080066
67private:
Mikhail Naganovadca70f2018-07-09 12:49:25 -070068 AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
Mikhail Naganov444ecc32018-05-01 17:40:05 -070069 sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
Mikhail Naganovadca70f2018-07-09 12:49:25 -070070 void addSoftwarePatchToInsertedModules(
Eric Laurent74c38dc2020-12-23 18:19:44 +010071 audio_module_handle_t module, audio_patch_handle_t handle,
72 const struct audio_patch *patch);
Mikhail Naganovadca70f2018-07-09 12:49:25 -070073 void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
François Gaffie58e73af2023-02-15 11:47:24 +010074 /**
75 * erase the patch referred by its handle.
76 * @param handle of the patch to be erased
77 * @param reuseExistingHalPatch if set, do not trig the callback of listeners, listener
78 * would receive instead a onUpdateAudioPatch when the patch will be recreated.
79 * It prevents for example DeviceEffectManager to spuriously remove / add a device on an already
80 * opened input / output mix.
81 */
82 void erasePatch(audio_patch_handle_t handle, bool reuseExistingHalPatch = false);
83
84 /**
85 * Returns true if the old and new patches passed as arguments describe the same
86 * connections between the first sink and the first source
87 * @param oldPatch previous patch
88 * @param newPatch new patch
89 * @return true if the route is unchanged between the old and new patch, false otherwise
90 */
91 inline bool patchesHaveSameRoute(
92 const struct audio_patch &newPatch, const struct audio_patch &oldPatch) const {
93 return (newPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
94 oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
95 newPatch.sources[0].id == oldPatch.sources[0].id &&
96 newPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
97 oldPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
98 newPatch.sinks[0].ext.mix.handle == oldPatch.sinks[0].ext.mix.handle) ||
99 (newPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
100 oldPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
101 newPatch.sinks[0].id == oldPatch.sinks[0].id &&
102 newPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
103 oldPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
104 newPatch.sources[0].ext.mix.handle == oldPatch.sources[0].ext.mix.handle);
105 }
Mikhail Naganov444ecc32018-05-01 17:40:05 -0700106
Mikhail Naganovdea53042018-04-26 13:10:21 -0700107 AudioFlinger &mAudioFlinger;
108 std::map<audio_patch_handle_t, Patch> mPatches;
Mikhail Naganovadca70f2018-07-09 12:49:25 -0700109
110 // This map allows going from a thread to "downstream" software patches
111 // when a processing module inserted in between. Example:
112 //
113 // from map value.streams map key
114 // [Mixer thread] --> [Virtual output device] --> [Processing module] ---\
115 // [Harware module] <-- [Physical output device] <-- [S/W Patch] <--/
116 // from map value.sw_patches
117 //
118 // This allows the mixer thread to look up the threads of the software patch
119 // for propagating timing info, parameters, etc.
120 //
121 // The current assumptions are:
122 // 1) The processing module acts as a mixer with several outputs which
123 // represent differently downmixed and / or encoded versions of the same
124 // mixed stream. There is no 1:1 correspondence between the input streams
125 // and the software patches, but rather a N:N correspondence between
126 // a group of streams and a group of patches.
127 // 2) There are only a couple of inserted processing modules in the system,
128 // so when looking for a stream or patch handle we can iterate over
129 // all modules.
130 struct ModuleConnections {
131 std::set<audio_io_handle_t> streams;
132 std::set<audio_patch_handle_t> sw_patches;
133 };
134 std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
Eric Laurent1c333e22014-05-20 10:48:17 -0700135};
Andy Hung6ac17eb2023-06-20 18:56:17 -0700136
137private: