blob: 6ef4d1a47a06bef46e558e6629a1c28643df3048 [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
Andy Hung8e6b62a2023-07-13 18:11:33 -070018#pragma once
Eric Laurent1c333e22014-05-20 10:48:17 -070019
Andy Hung8e6b62a2023-07-13 18:11:33 -070020namespace android {
21
Andy Hungb6692eb2023-07-13 16:52:46 -070022class PatchPanel : public IAfPatchPanel {
Eric Laurent1c333e22014-05-20 10:48:17 -070023public:
Mikhail Naganovdea53042018-04-26 13:10:21 -070024 explicit PatchPanel(AudioFlinger* audioFlinger) : mAudioFlinger(*audioFlinger) {}
Eric Laurent1c333e22014-05-20 10:48:17 -070025
26 /* List connected audio ports and their attributes */
27 status_t listAudioPorts(unsigned int *num_ports,
Andy Hungb6692eb2023-07-13 16:52:46 -070028 struct audio_port* ports) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070029
30 /* Get supported attributes for a given audio port */
Andy Hungb6692eb2023-07-13 16:52:46 -070031 status_t getAudioPort(struct audio_port_v7* port) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070032
33 /* Create a patch between several source and sink ports */
34 status_t createAudioPatch(const struct audio_patch *patch,
Francois Gaffiee0dc36d2021-04-01 16:01:00 +020035 audio_patch_handle_t *handle,
Andy Hungb6692eb2023-07-13 16:52:46 -070036 bool endpointPatch = false) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070037
38 /* Release a patch */
Andy Hungb6692eb2023-07-13 16:52:46 -070039 status_t releaseAudioPatch(audio_patch_handle_t handle) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070040
41 /* List connected audio devices and they attributes */
42 status_t listAudioPatches(unsigned int *num_patches,
Andy Hungb6692eb2023-07-13 16:52:46 -070043 struct audio_patch* patches) final;
Eric Laurent1c333e22014-05-20 10:48:17 -070044
Mikhail Naganovadca70f2018-07-09 12:49:25 -070045 // Retrieves all currently estrablished software patches for a stream
46 // opened on an intermediate module.
47 status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
Andy Hungb6692eb2023-07-13 16:52:46 -070048 std::vector<SoftwarePatch>* patches) const final;
Mikhail Naganovadca70f2018-07-09 12:49:25 -070049
50 // Notifies patch panel about all opened and closed streams.
Eric Laurent74c38dc2020-12-23 18:19:44 +010051 void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
Andy Hungb6692eb2023-07-13 16:52:46 -070052 struct audio_patch* patch) final;
53 void notifyStreamClosed(audio_io_handle_t stream) final;
Mikhail Naganovadca70f2018-07-09 12:49:25 -070054
Andy Hungb6692eb2023-07-13 16:52:46 -070055 void dump(int fd) const final;
Eric Laurent83b88082014-06-20 18:31:16 -070056
Eric Laurent9b2064c2019-11-22 17:25:04 -080057 // Call with AudioFlinger mLock held
Andy Hungb6692eb2023-07-13 16:52:46 -070058 const std::map<audio_patch_handle_t, Patch>& patches_l() const final { return mPatches; }
59
60 // Must be called under AudioFlinger::mLock
61 status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final;
62
63 void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final;
Eric Laurent9b2064c2019-11-22 17:25:04 -080064
65private:
Mikhail Naganovadca70f2018-07-09 12:49:25 -070066 AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
Mikhail Naganov444ecc32018-05-01 17:40:05 -070067 sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
Mikhail Naganovadca70f2018-07-09 12:49:25 -070068 void addSoftwarePatchToInsertedModules(
Eric Laurent74c38dc2020-12-23 18:19:44 +010069 audio_module_handle_t module, audio_patch_handle_t handle,
70 const struct audio_patch *patch);
Mikhail Naganovadca70f2018-07-09 12:49:25 -070071 void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
François Gaffie58e73af2023-02-15 11:47:24 +010072 /**
73 * erase the patch referred by its handle.
74 * @param handle of the patch to be erased
75 * @param reuseExistingHalPatch if set, do not trig the callback of listeners, listener
76 * would receive instead a onUpdateAudioPatch when the patch will be recreated.
77 * It prevents for example DeviceEffectManager to spuriously remove / add a device on an already
78 * opened input / output mix.
79 */
80 void erasePatch(audio_patch_handle_t handle, bool reuseExistingHalPatch = false);
81
82 /**
83 * Returns true if the old and new patches passed as arguments describe the same
84 * connections between the first sink and the first source
85 * @param oldPatch previous patch
86 * @param newPatch new patch
87 * @return true if the route is unchanged between the old and new patch, false otherwise
88 */
89 inline bool patchesHaveSameRoute(
90 const struct audio_patch &newPatch, const struct audio_patch &oldPatch) const {
91 return (newPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
92 oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
93 newPatch.sources[0].id == oldPatch.sources[0].id &&
94 newPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
95 oldPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
96 newPatch.sinks[0].ext.mix.handle == oldPatch.sinks[0].ext.mix.handle) ||
97 (newPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
98 oldPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
99 newPatch.sinks[0].id == oldPatch.sinks[0].id &&
100 newPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
101 oldPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
102 newPatch.sources[0].ext.mix.handle == oldPatch.sources[0].ext.mix.handle);
103 }
Mikhail Naganov444ecc32018-05-01 17:40:05 -0700104
Mikhail Naganovdea53042018-04-26 13:10:21 -0700105 AudioFlinger &mAudioFlinger;
106 std::map<audio_patch_handle_t, Patch> mPatches;
Mikhail Naganovadca70f2018-07-09 12:49:25 -0700107
108 // This map allows going from a thread to "downstream" software patches
109 // when a processing module inserted in between. Example:
110 //
111 // from map value.streams map key
112 // [Mixer thread] --> [Virtual output device] --> [Processing module] ---\
113 // [Harware module] <-- [Physical output device] <-- [S/W Patch] <--/
114 // from map value.sw_patches
115 //
116 // This allows the mixer thread to look up the threads of the software patch
117 // for propagating timing info, parameters, etc.
118 //
119 // The current assumptions are:
120 // 1) The processing module acts as a mixer with several outputs which
121 // represent differently downmixed and / or encoded versions of the same
122 // mixed stream. There is no 1:1 correspondence between the input streams
123 // and the software patches, but rather a N:N correspondence between
124 // a group of streams and a group of patches.
125 // 2) There are only a couple of inserted processing modules in the system,
126 // so when looking for a stream or patch handle we can iterate over
127 // all modules.
128 struct ModuleConnections {
129 std::set<audio_io_handle_t> streams;
130 std::set<audio_patch_handle_t> sw_patches;
131 };
132 std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
Eric Laurent1c333e22014-05-20 10:48:17 -0700133};
Andy Hung6ac17eb2023-06-20 18:56:17 -0700134
Andy Hung8e6b62a2023-07-13 18:11:33 -0700135} // namespace android