1*ec779b8eSAndroid Build Coastguard Worker /* 2*ec779b8eSAndroid Build Coastguard Worker ** 3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2014, The Android Open Source Project 4*ec779b8eSAndroid Build Coastguard Worker ** 5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License"); 6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License. 7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at 8*ec779b8eSAndroid Build Coastguard Worker ** 9*ec779b8eSAndroid Build Coastguard Worker ** http://www.apache.org/licenses/LICENSE-2.0 10*ec779b8eSAndroid Build Coastguard Worker ** 11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software 12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS, 13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and 15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License. 16*ec779b8eSAndroid Build Coastguard Worker */ 17*ec779b8eSAndroid Build Coastguard Worker 18*ec779b8eSAndroid Build Coastguard Worker #pragma once 19*ec779b8eSAndroid Build Coastguard Worker 20*ec779b8eSAndroid Build Coastguard Worker #include "IAfPatchPanel.h" 21*ec779b8eSAndroid Build Coastguard Worker 22*ec779b8eSAndroid Build Coastguard Worker #include <map> // avoid transitive dependency 23*ec779b8eSAndroid Build Coastguard Worker #include <set> // avoid transitive dependency 24*ec779b8eSAndroid Build Coastguard Worker 25*ec779b8eSAndroid Build Coastguard Worker namespace android { 26*ec779b8eSAndroid Build Coastguard Worker 27*ec779b8eSAndroid Build Coastguard Worker class PatchPanel : public IAfPatchPanel { 28*ec779b8eSAndroid Build Coastguard Worker public: PatchPanel(const sp<IAfPatchPanelCallback> & afPatchPanelCallback)29*ec779b8eSAndroid Build Coastguard Worker explicit PatchPanel(const sp<IAfPatchPanelCallback>& afPatchPanelCallback) 30*ec779b8eSAndroid Build Coastguard Worker : mAfPatchPanelCallback(afPatchPanelCallback) {} 31*ec779b8eSAndroid Build Coastguard Worker 32*ec779b8eSAndroid Build Coastguard Worker /* List connected audio ports and their attributes */ 33*ec779b8eSAndroid Build Coastguard Worker status_t listAudioPorts_l(unsigned int *num_ports, 34*ec779b8eSAndroid Build Coastguard Worker struct audio_port* ports) final REQUIRES(audio_utils::AudioFlinger_Mutex); 35*ec779b8eSAndroid Build Coastguard Worker 36*ec779b8eSAndroid Build Coastguard Worker /* Get supported attributes for a given audio port */ 37*ec779b8eSAndroid Build Coastguard Worker status_t getAudioPort_l(struct audio_port_v7* port) final 38*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 39*ec779b8eSAndroid Build Coastguard Worker 40*ec779b8eSAndroid Build Coastguard Worker /* Create a patch between several source and sink ports */ 41*ec779b8eSAndroid Build Coastguard Worker status_t createAudioPatch_l(const struct audio_patch *patch, 42*ec779b8eSAndroid Build Coastguard Worker audio_patch_handle_t *handle, 43*ec779b8eSAndroid Build Coastguard Worker bool endpointPatch = false) final 44*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 45*ec779b8eSAndroid Build Coastguard Worker 46*ec779b8eSAndroid Build Coastguard Worker /* Release a patch */ 47*ec779b8eSAndroid Build Coastguard Worker status_t releaseAudioPatch_l(audio_patch_handle_t handle) final 48*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 49*ec779b8eSAndroid Build Coastguard Worker 50*ec779b8eSAndroid Build Coastguard Worker /* List connected audio devices and they attributes */ 51*ec779b8eSAndroid Build Coastguard Worker status_t listAudioPatches_l(unsigned int *num_patches, 52*ec779b8eSAndroid Build Coastguard Worker struct audio_patch* patches) final 53*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 54*ec779b8eSAndroid Build Coastguard Worker 55*ec779b8eSAndroid Build Coastguard Worker // Retrieves all currently established software patches for a stream 56*ec779b8eSAndroid Build Coastguard Worker // opened on an intermediate module. 57*ec779b8eSAndroid Build Coastguard Worker status_t getDownstreamSoftwarePatches(audio_io_handle_t stream, 58*ec779b8eSAndroid Build Coastguard Worker std::vector<SoftwarePatch>* patches) const final; 59*ec779b8eSAndroid Build Coastguard Worker 60*ec779b8eSAndroid Build Coastguard Worker // Notifies patch panel about all opened and closed streams. 61*ec779b8eSAndroid Build Coastguard Worker void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream, 62*ec779b8eSAndroid Build Coastguard Worker struct audio_patch* patch) final; 63*ec779b8eSAndroid Build Coastguard Worker void notifyStreamClosed(audio_io_handle_t stream) final; 64*ec779b8eSAndroid Build Coastguard Worker 65*ec779b8eSAndroid Build Coastguard Worker void dump(int fd) const final; 66*ec779b8eSAndroid Build Coastguard Worker patches_l()67*ec779b8eSAndroid Build Coastguard Worker const std::map<audio_patch_handle_t, Patch>& patches_l() const final 68*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex) { return mPatches; } 69*ec779b8eSAndroid Build Coastguard Worker 70*ec779b8eSAndroid Build Coastguard Worker status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final 71*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 72*ec779b8eSAndroid Build Coastguard Worker 73*ec779b8eSAndroid Build Coastguard Worker void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final 74*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 75*ec779b8eSAndroid Build Coastguard Worker 76*ec779b8eSAndroid Build Coastguard Worker /** 77*ec779b8eSAndroid Build Coastguard Worker * Get the attributes of the mix port when connecting to the given device port 78*ec779b8eSAndroid Build Coastguard Worker */ 79*ec779b8eSAndroid Build Coastguard Worker status_t getAudioMixPort_l(const audio_port_v7* devicePort, audio_port_v7* mixPort) final 80*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 81*ec779b8eSAndroid Build Coastguard Worker 82*ec779b8eSAndroid Build Coastguard Worker private: 83*ec779b8eSAndroid Build Coastguard Worker AudioHwDevice* findAudioHwDeviceByModule_l(audio_module_handle_t module) 84*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 85*ec779b8eSAndroid Build Coastguard Worker sp<DeviceHalInterface> findHwDeviceByModule_l(audio_module_handle_t module) 86*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 87*ec779b8eSAndroid Build Coastguard Worker void addSoftwarePatchToInsertedModules_l( 88*ec779b8eSAndroid Build Coastguard Worker audio_module_handle_t module, audio_patch_handle_t handle, 89*ec779b8eSAndroid Build Coastguard Worker const struct audio_patch *patch) 90*ec779b8eSAndroid Build Coastguard Worker REQUIRES(audio_utils::AudioFlinger_Mutex); 91*ec779b8eSAndroid Build Coastguard Worker void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle); 92*ec779b8eSAndroid Build Coastguard Worker /** 93*ec779b8eSAndroid Build Coastguard Worker * erase the patch referred by its handle. 94*ec779b8eSAndroid Build Coastguard Worker * @param handle of the patch to be erased 95*ec779b8eSAndroid Build Coastguard Worker * @param reuseExistingHalPatch if set, do not trig the callback of listeners, listener 96*ec779b8eSAndroid Build Coastguard Worker * would receive instead a onUpdateAudioPatch when the patch will be recreated. 97*ec779b8eSAndroid Build Coastguard Worker * It prevents for example DeviceEffectManager to spuriously remove / add a device on an already 98*ec779b8eSAndroid Build Coastguard Worker * opened input / output mix. 99*ec779b8eSAndroid Build Coastguard Worker */ 100*ec779b8eSAndroid Build Coastguard Worker void erasePatch(audio_patch_handle_t handle, bool reuseExistingHalPatch = false); 101*ec779b8eSAndroid Build Coastguard Worker 102*ec779b8eSAndroid Build Coastguard Worker /** 103*ec779b8eSAndroid Build Coastguard Worker * Returns true if the old and new patches passed as arguments describe the same 104*ec779b8eSAndroid Build Coastguard Worker * connections between the first sink and the first source 105*ec779b8eSAndroid Build Coastguard Worker * @param oldPatch previous patch 106*ec779b8eSAndroid Build Coastguard Worker * @param newPatch new patch 107*ec779b8eSAndroid Build Coastguard Worker * @return true if the route is unchanged between the old and new patch, false otherwise 108*ec779b8eSAndroid Build Coastguard Worker */ patchesHaveSameRoute(const struct audio_patch & newPatch,const struct audio_patch & oldPatch)109*ec779b8eSAndroid Build Coastguard Worker inline bool patchesHaveSameRoute( 110*ec779b8eSAndroid Build Coastguard Worker const struct audio_patch &newPatch, const struct audio_patch &oldPatch) const { 111*ec779b8eSAndroid Build Coastguard Worker return (newPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE && 112*ec779b8eSAndroid Build Coastguard Worker oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE && 113*ec779b8eSAndroid Build Coastguard Worker newPatch.sources[0].id == oldPatch.sources[0].id && 114*ec779b8eSAndroid Build Coastguard Worker newPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX && 115*ec779b8eSAndroid Build Coastguard Worker oldPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX && 116*ec779b8eSAndroid Build Coastguard Worker newPatch.sinks[0].ext.mix.handle == oldPatch.sinks[0].ext.mix.handle) || 117*ec779b8eSAndroid Build Coastguard Worker (newPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE && 118*ec779b8eSAndroid Build Coastguard Worker oldPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE && 119*ec779b8eSAndroid Build Coastguard Worker newPatch.sinks[0].id == oldPatch.sinks[0].id && 120*ec779b8eSAndroid Build Coastguard Worker newPatch.sources[0].type == AUDIO_PORT_TYPE_MIX && 121*ec779b8eSAndroid Build Coastguard Worker oldPatch.sources[0].type == AUDIO_PORT_TYPE_MIX && 122*ec779b8eSAndroid Build Coastguard Worker newPatch.sources[0].ext.mix.handle == oldPatch.sources[0].ext.mix.handle); 123*ec779b8eSAndroid Build Coastguard Worker } 124*ec779b8eSAndroid Build Coastguard Worker 125*ec779b8eSAndroid Build Coastguard Worker const sp<IAfPatchPanelCallback> mAfPatchPanelCallback; 126*ec779b8eSAndroid Build Coastguard Worker std::map<audio_patch_handle_t, Patch> mPatches; 127*ec779b8eSAndroid Build Coastguard Worker 128*ec779b8eSAndroid Build Coastguard Worker // This map allows going from a thread to "downstream" software patches 129*ec779b8eSAndroid Build Coastguard Worker // when a processing module inserted in between. Example: 130*ec779b8eSAndroid Build Coastguard Worker // 131*ec779b8eSAndroid Build Coastguard Worker // from map value.streams map key 132*ec779b8eSAndroid Build Coastguard Worker // [Mixer thread] --> [Virtual output device] --> [Processing module] ---\ 133*ec779b8eSAndroid Build Coastguard Worker // [Harware module] <-- [Physical output device] <-- [S/W Patch] <--/ 134*ec779b8eSAndroid Build Coastguard Worker // from map value.sw_patches 135*ec779b8eSAndroid Build Coastguard Worker // 136*ec779b8eSAndroid Build Coastguard Worker // This allows the mixer thread to look up the threads of the software patch 137*ec779b8eSAndroid Build Coastguard Worker // for propagating timing info, parameters, etc. 138*ec779b8eSAndroid Build Coastguard Worker // 139*ec779b8eSAndroid Build Coastguard Worker // The current assumptions are: 140*ec779b8eSAndroid Build Coastguard Worker // 1) The processing module acts as a mixer with several outputs which 141*ec779b8eSAndroid Build Coastguard Worker // represent differently downmixed and / or encoded versions of the same 142*ec779b8eSAndroid Build Coastguard Worker // mixed stream. There is no 1:1 correspondence between the input streams 143*ec779b8eSAndroid Build Coastguard Worker // and the software patches, but rather a N:N correspondence between 144*ec779b8eSAndroid Build Coastguard Worker // a group of streams and a group of patches. 145*ec779b8eSAndroid Build Coastguard Worker // 2) There are only a couple of inserted processing modules in the system, 146*ec779b8eSAndroid Build Coastguard Worker // so when looking for a stream or patch handle we can iterate over 147*ec779b8eSAndroid Build Coastguard Worker // all modules. 148*ec779b8eSAndroid Build Coastguard Worker struct ModuleConnections { 149*ec779b8eSAndroid Build Coastguard Worker std::set<audio_io_handle_t> streams; 150*ec779b8eSAndroid Build Coastguard Worker std::set<audio_patch_handle_t> sw_patches; 151*ec779b8eSAndroid Build Coastguard Worker }; 152*ec779b8eSAndroid Build Coastguard Worker std::map<audio_module_handle_t, ModuleConnections> mInsertedModules; 153*ec779b8eSAndroid Build Coastguard Worker }; 154*ec779b8eSAndroid Build Coastguard Worker 155*ec779b8eSAndroid Build Coastguard Worker } // namespace android 156