blob: f84b40ed61097e037be6d63e9c70503f3b51f116 [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 Hung00b9aea2023-07-18 18:43:08 -070020#include "IAfPatchPanel.h"
21
22#include <map> // avoid transitive dependency
23#include <set> // avoid transitive dependency
24
Andy Hung8e6b62a2023-07-13 18:11:33 -070025namespace android {
26
Andy Hungb6692eb2023-07-13 16:52:46 -070027class PatchPanel : public IAfPatchPanel {
Eric Laurent1c333e22014-05-20 10:48:17 -070028public:
Andy Hung2dc61c42023-07-17 14:36:08 -070029 explicit PatchPanel(const sp<IAfPatchPanelCallback>& afPatchPanelCallback)
30 : mAfPatchPanelCallback(afPatchPanelCallback) {}
Eric Laurent1c333e22014-05-20 10:48:17 -070031
32 /* List connected audio ports and their attributes */
Andy Hung37006372023-08-31 15:24:24 -070033 status_t listAudioPorts_l(unsigned int *num_ports,
34 struct audio_port* ports) final REQUIRES(audio_utils::AudioFlinger_Mutex);
Eric Laurent1c333e22014-05-20 10:48:17 -070035
36 /* Get supported attributes for a given audio port */
Andy Hung37006372023-08-31 15:24:24 -070037 status_t getAudioPort_l(struct audio_port_v7* port) final
38 REQUIRES(audio_utils::AudioFlinger_Mutex);
Eric Laurent1c333e22014-05-20 10:48:17 -070039
40 /* Create a patch between several source and sink ports */
Andy Hung37006372023-08-31 15:24:24 -070041 status_t createAudioPatch_l(const struct audio_patch *patch,
Francois Gaffiee0dc36d2021-04-01 16:01:00 +020042 audio_patch_handle_t *handle,
Andy Hung37006372023-08-31 15:24:24 -070043 bool endpointPatch = false) final
44 REQUIRES(audio_utils::AudioFlinger_Mutex);
Eric Laurent1c333e22014-05-20 10:48:17 -070045
46 /* Release a patch */
Andy Hung37006372023-08-31 15:24:24 -070047 status_t releaseAudioPatch_l(audio_patch_handle_t handle) final
48 REQUIRES(audio_utils::AudioFlinger_Mutex);
Eric Laurent1c333e22014-05-20 10:48:17 -070049
50 /* List connected audio devices and they attributes */
Andy Hung37006372023-08-31 15:24:24 -070051 status_t listAudioPatches_l(unsigned int *num_patches,
52 struct audio_patch* patches) final
53 REQUIRES(audio_utils::AudioFlinger_Mutex);
Eric Laurent1c333e22014-05-20 10:48:17 -070054
Andy Hung37006372023-08-31 15:24:24 -070055 // Retrieves all currently established software patches for a stream
Mikhail Naganovadca70f2018-07-09 12:49:25 -070056 // opened on an intermediate module.
57 status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
Andy Hungb6692eb2023-07-13 16:52:46 -070058 std::vector<SoftwarePatch>* patches) const final;
Mikhail Naganovadca70f2018-07-09 12:49:25 -070059
60 // Notifies patch panel about all opened and closed streams.
Eric Laurent74c38dc2020-12-23 18:19:44 +010061 void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
Andy Hungb6692eb2023-07-13 16:52:46 -070062 struct audio_patch* patch) final;
63 void notifyStreamClosed(audio_io_handle_t stream) final;
Mikhail Naganovadca70f2018-07-09 12:49:25 -070064
Andy Hungb6692eb2023-07-13 16:52:46 -070065 void dump(int fd) const final;
Eric Laurent83b88082014-06-20 18:31:16 -070066
Andy Hung37006372023-08-31 15:24:24 -070067 const std::map<audio_patch_handle_t, Patch>& patches_l() const final
68 REQUIRES(audio_utils::AudioFlinger_Mutex) { return mPatches; }
Andy Hungb6692eb2023-07-13 16:52:46 -070069
Andy Hung37006372023-08-31 15:24:24 -070070 status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final
71 REQUIRES(audio_utils::AudioFlinger_Mutex);
Andy Hungb6692eb2023-07-13 16:52:46 -070072
Andy Hung37006372023-08-31 15:24:24 -070073 void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final
74 REQUIRES(audio_utils::AudioFlinger_Mutex);
Eric Laurent9b2064c2019-11-22 17:25:04 -080075
jiabin12537fc2023-10-12 17:56:08 +000076 /**
77 * Get the attributes of the mix port when connecting to the given device port
78 */
79 status_t getAudioMixPort_l(const audio_port_v7* devicePort, audio_port_v7* mixPort) final
80 REQUIRES(audio_utils::AudioFlinger_Mutex);
81
Eric Laurent9b2064c2019-11-22 17:25:04 -080082private:
Andy Hung37006372023-08-31 15:24:24 -070083 AudioHwDevice* findAudioHwDeviceByModule_l(audio_module_handle_t module)
84 REQUIRES(audio_utils::AudioFlinger_Mutex);
85 sp<DeviceHalInterface> findHwDeviceByModule_l(audio_module_handle_t module)
86 REQUIRES(audio_utils::AudioFlinger_Mutex);
87 void addSoftwarePatchToInsertedModules_l(
Eric Laurent74c38dc2020-12-23 18:19:44 +010088 audio_module_handle_t module, audio_patch_handle_t handle,
Andy Hung37006372023-08-31 15:24:24 -070089 const struct audio_patch *patch)
90 REQUIRES(audio_utils::AudioFlinger_Mutex);
Mikhail Naganovadca70f2018-07-09 12:49:25 -070091 void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
François Gaffie58e73af2023-02-15 11:47:24 +010092 /**
93 * erase the patch referred by its handle.
94 * @param handle of the patch to be erased
95 * @param reuseExistingHalPatch if set, do not trig the callback of listeners, listener
96 * would receive instead a onUpdateAudioPatch when the patch will be recreated.
97 * It prevents for example DeviceEffectManager to spuriously remove / add a device on an already
98 * opened input / output mix.
99 */
100 void erasePatch(audio_patch_handle_t handle, bool reuseExistingHalPatch = false);
101
102 /**
103 * Returns true if the old and new patches passed as arguments describe the same
104 * connections between the first sink and the first source
105 * @param oldPatch previous patch
106 * @param newPatch new patch
107 * @return true if the route is unchanged between the old and new patch, false otherwise
108 */
109 inline bool patchesHaveSameRoute(
110 const struct audio_patch &newPatch, const struct audio_patch &oldPatch) const {
111 return (newPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
112 oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
113 newPatch.sources[0].id == oldPatch.sources[0].id &&
114 newPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
115 oldPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
116 newPatch.sinks[0].ext.mix.handle == oldPatch.sinks[0].ext.mix.handle) ||
117 (newPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
118 oldPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
119 newPatch.sinks[0].id == oldPatch.sinks[0].id &&
120 newPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
121 oldPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
122 newPatch.sources[0].ext.mix.handle == oldPatch.sources[0].ext.mix.handle);
123 }
Mikhail Naganov444ecc32018-05-01 17:40:05 -0700124
Andy Hung2dc61c42023-07-17 14:36:08 -0700125 const sp<IAfPatchPanelCallback> mAfPatchPanelCallback;
Mikhail Naganovdea53042018-04-26 13:10:21 -0700126 std::map<audio_patch_handle_t, Patch> mPatches;
Mikhail Naganovadca70f2018-07-09 12:49:25 -0700127
128 // This map allows going from a thread to "downstream" software patches
129 // when a processing module inserted in between. Example:
130 //
131 // from map value.streams map key
132 // [Mixer thread] --> [Virtual output device] --> [Processing module] ---\
133 // [Harware module] <-- [Physical output device] <-- [S/W Patch] <--/
134 // from map value.sw_patches
135 //
136 // This allows the mixer thread to look up the threads of the software patch
137 // for propagating timing info, parameters, etc.
138 //
139 // The current assumptions are:
140 // 1) The processing module acts as a mixer with several outputs which
141 // represent differently downmixed and / or encoded versions of the same
142 // mixed stream. There is no 1:1 correspondence between the input streams
143 // and the software patches, but rather a N:N correspondence between
144 // a group of streams and a group of patches.
145 // 2) There are only a couple of inserted processing modules in the system,
146 // so when looking for a stream or patch handle we can iterate over
147 // all modules.
148 struct ModuleConnections {
149 std::set<audio_io_handle_t> streams;
150 std::set<audio_patch_handle_t> sw_patches;
151 };
152 std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
Eric Laurent1c333e22014-05-20 10:48:17 -0700153};
Andy Hung6ac17eb2023-06-20 18:56:17 -0700154
Andy Hung8e6b62a2023-07-13 18:11:33 -0700155} // namespace android