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