• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #pragma once
19 
20 #include "IAfPatchPanel.h"
21 
22 #include <map>  // avoid transitive dependency
23 #include <set>  // avoid transitive dependency
24 
25 namespace android {
26 
27 class PatchPanel : public IAfPatchPanel {
28 public:
PatchPanel(const sp<IAfPatchPanelCallback> & afPatchPanelCallback)29     explicit PatchPanel(const sp<IAfPatchPanelCallback>& afPatchPanelCallback)
30         : mAfPatchPanelCallback(afPatchPanelCallback) {}
31 
32     /* List connected audio ports and their attributes */
33     status_t listAudioPorts_l(unsigned int *num_ports,
34             struct audio_port* ports) final REQUIRES(audio_utils::AudioFlinger_Mutex);
35 
36     /* Get supported attributes for a given audio port */
37     status_t getAudioPort_l(struct audio_port_v7* port) final
38             REQUIRES(audio_utils::AudioFlinger_Mutex);
39 
40     /* Create a patch between several source and sink ports */
41     status_t createAudioPatch_l(const struct audio_patch *patch,
42                               audio_patch_handle_t *handle,
43                               bool endpointPatch = false) final
44             REQUIRES(audio_utils::AudioFlinger_Mutex);
45 
46     /* Release a patch */
47     status_t releaseAudioPatch_l(audio_patch_handle_t handle) final
48             REQUIRES(audio_utils::AudioFlinger_Mutex);
49 
50     /* List connected audio devices and they attributes */
51     status_t listAudioPatches_l(unsigned int *num_patches,
52             struct audio_patch* patches) final
53             REQUIRES(audio_utils::AudioFlinger_Mutex);
54 
55     // Retrieves all currently established software patches for a stream
56     // opened on an intermediate module.
57     status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
58             std::vector<SoftwarePatch>* patches) const final;
59 
60     // Notifies patch panel about all opened and closed streams.
61     void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
62                             struct audio_patch* patch) final;
63     void notifyStreamClosed(audio_io_handle_t stream) final;
64 
65     void dump(int fd) const final;
66 
patches_l()67     const std::map<audio_patch_handle_t, Patch>& patches_l() const final
68             REQUIRES(audio_utils::AudioFlinger_Mutex) { return mPatches; }
69 
70     status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final
71             REQUIRES(audio_utils::AudioFlinger_Mutex);
72 
73     void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final
74             REQUIRES(audio_utils::AudioFlinger_Mutex);
75 
76     /**
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 
82 private:
83     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(
88             audio_module_handle_t module, audio_patch_handle_t handle,
89             const struct audio_patch *patch)
90             REQUIRES(audio_utils::AudioFlinger_Mutex);
91     void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
92     /**
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      */
patchesHaveSameRoute(const struct audio_patch & newPatch,const struct audio_patch & oldPatch)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     }
124 
125     const sp<IAfPatchPanelCallback> mAfPatchPanelCallback;
126     std::map<audio_patch_handle_t, Patch> mPatches;
127 
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;
153 };
154 
155 }  // namespace android
156