From 53615e29c99c5e9d2ca77aaefd7bf5c770513120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Gaffie?= Date: Thu, 19 Mar 2015 09:24:12 +0100 Subject: Migrate helper functions from managerdefault to common MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch moves from manager to common: -parse helper functions of the policy configuration file -collection helper function on -output / input descriptors -DeviceDescriptor -AudioPatch / Audio Port -IO Profile -HwModule Change-Id: If45e53418db75af1af198f43c4ef27884499055f Signed-off-by: François Gaffie --- services/audiopolicy/common/include/policy.h | 84 +++++++++++ .../common/managerdefinitions/Android.mk | 1 + .../include/AudioInputDescriptor.h | 26 ++++ .../include/AudioOutputDescriptor.h | 37 +++++ .../common/managerdefinitions/include/AudioPatch.h | 14 ++ .../common/managerdefinitions/include/AudioPort.h | 11 +- .../include/ConfigParsingUtils.h | 36 ++++- .../managerdefinitions/include/DeviceDescriptor.h | 24 ++- .../common/managerdefinitions/include/HwModule.h | 16 ++ .../src/AudioInputDescriptor.cpp | 87 ++++++++++- .../src/AudioOutputDescriptor.cpp | 118 ++++++++++++++- .../common/managerdefinitions/src/AudioPatch.cpp | 70 +++++++++ .../common/managerdefinitions/src/AudioPort.cpp | 8 +- .../managerdefinitions/src/ConfigParsingUtils.cpp | 166 +++++++++++++++++++++ .../managerdefinitions/src/DeviceDescriptor.cpp | 53 +++++-- .../common/managerdefinitions/src/HwModule.cpp | 89 +++++++++++ .../common/managerdefinitions/src/IOProfile.cpp | 12 +- 17 files changed, 811 insertions(+), 41 deletions(-) create mode 100755 services/audiopolicy/common/include/policy.h (limited to 'services/audiopolicy/common') diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h new file mode 100755 index 0000000..a2327ee --- /dev/null +++ b/services/audiopolicy/common/include/policy.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +// For mixed output and inputs, the policy will use max mixer sampling rates. +// Do not limit sampling rate otherwise +#define MAX_MIXER_SAMPLING_RATE 48000 + +// For mixed output and inputs, the policy will use max mixer channel count. +// Do not limit channel count otherwise +#define MAX_MIXER_CHANNEL_COUNT 8 + +/** + * A device mask for all audio input devices that are considered "virtual" when evaluating + * active inputs in getActiveInput() + */ +#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER) + + +/** + * A device mask for all audio input and output devices where matching inputs/outputs on device + * type alone is not enough: the address must match too + */ +#define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \ + AUDIO_DEVICE_OUT_REMOTE_SUBMIX) + +/** + * Check if the state given correspond to an in call state. + * @TODO find a better name for widely call state + * + * @param[in] state to consider + * + * @return true if given state represents a device in a telephony or VoIP call + */ +static inline bool is_state_in_call(int state) +{ + return (state == AUDIO_MODE_IN_CALL) || (state == AUDIO_MODE_IN_COMMUNICATION); +} + +/** + * Check if the input device given is considered as a virtual device. + * + * @param[in] device to consider + * + * @return true if the device is a virtual one, false otherwise. + */ +static bool is_virtual_input_device(audio_devices_t device) +{ + if ((device & AUDIO_DEVICE_BIT_IN) != 0) { + device &= ~AUDIO_DEVICE_BIT_IN; + if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0)) + return true; + } + return false; +} + +/** + * Check whether the device type is one + * where addresses are used to distinguish between one connected device and another + * + * @param[in] device to consider + * + * @return true if the device needs distinguish on address, false otherwise.. + */ +static bool device_distinguishes_on_address(audio_devices_t device) +{ + return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0); +} diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk index d9d1477..bc6900b 100644 --- a/services/audiopolicy/common/managerdefinitions/Android.mk +++ b/services/audiopolicy/common/managerdefinitions/Android.mk @@ -20,6 +20,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/include \ + $(TOPDIR)frameworks/av/services/audiopolicy/common/include \ LOCAL_EXPORT_C_INCLUDE_DIRS := \ $(LOCAL_PATH)/include diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h index 599c295..7536a37 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h @@ -20,6 +20,7 @@ #include #include #include +#include namespace android { @@ -34,6 +35,8 @@ public: AudioInputDescriptor(const sp& profile); void setIoHandle(audio_io_handle_t ioHandle); + audio_module_handle_t getModuleHandle() const; + status_t dump(int fd); audio_port_handle_t mId; @@ -56,4 +59,27 @@ public: void toAudioPort(struct audio_port *port) const; }; +class AudioInputCollection : + public DefaultKeyedVector< audio_io_handle_t, sp > +{ +public: + bool isSourceActive(audio_source_t source) const; + + sp getInputFromId(audio_port_handle_t id) const; + + uint32_t activeInputsCount() const; + + /** + * return io handle of active input or 0 if no input is active + * Only considers inputs from physical devices (e.g. main mic, headset mic) when + * ignoreVirtualInputs is true. + */ + audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true); + + audio_devices_t getSupportedDevices(audio_io_handle_t handle) const; + + status_t dump(int fd) const; +}; + + }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h index 8469b81..e2f1bbf 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h @@ -20,6 +20,7 @@ #include "ApmImplDefinitions.h" #include #include +#include #include namespace android { @@ -54,6 +55,8 @@ public: virtual sp getAudioPort() const { return mProfile; } void toAudioPort(struct audio_port *port) const; + audio_module_handle_t getModuleHandle() const; + audio_port_handle_t mId; audio_io_handle_t mIoHandle; // output handle uint32_t mLatency; // @@ -73,4 +76,38 @@ public: uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only) }; +class AudioOutputCollection : + public DefaultKeyedVector< audio_io_handle_t, sp > +{ +public: + bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const; + + /** + * return whether a stream is playing remotely, override to change the definition of + * local/remote playback, used for instance by notification manager to not make + * media players lose audio focus when not playing locally + * For the base implementation, "remotely" means playing during screen mirroring which + * uses an output for playback with a non-empty, non "0" address. + */ + bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const; + + /** + * returns the A2DP output handle if it is open or 0 otherwise + */ + audio_io_handle_t getA2dpOutput() const; + + sp getOutputFromId(audio_port_handle_t id) const; + + sp getPrimaryOutput() const; + + /** + * return true if any output is playing anything besides the stream to ignore + */ + bool isAnyOutputActive(audio_stream_type_t streamToIgnore) const; + + audio_devices_t getSupportedDevices(audio_io_handle_t handle) const; + + status_t dump(int fd) const; +}; + }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h index 6e8fb32..385f257 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h @@ -17,8 +17,10 @@ #pragma once #include +#include #include #include +#include namespace android { @@ -38,4 +40,16 @@ private: static volatile int32_t mNextUniqueId; }; +class AudioPatchCollection : public DefaultKeyedVector > +{ +public: + status_t addAudioPatch(audio_patch_handle_t handle, const sp& patch); + + status_t removeAudioPatch(audio_patch_handle_t handle); + + status_t listAudioPatches(unsigned int *num_patches, struct audio_patch *patches) const; + + status_t dump(int fd) const; +}; + }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h index 52e845c..4f7f2bc 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h @@ -23,19 +23,16 @@ #include #include -#define MAX_MIXER_SAMPLING_RATE 48000 -#define MAX_MIXER_CHANNEL_COUNT 8 - namespace android { class HwModule; class AudioGain; -class AudioPort: public virtual RefBase +class AudioPort : public virtual RefBase { public: AudioPort(const String8& name, audio_port_type_t type, - audio_port_role_t role, const sp& module); + audio_port_role_t role, const sp& module); virtual ~AudioPort() {} audio_port_handle_t getHandle() { return mId; } @@ -78,6 +75,8 @@ public: static const audio_format_t sPcmFormatCompareTable[]; static int compareFormats(audio_format_t format1, audio_format_t format2); + audio_module_handle_t getModuleHandle() const; + void dump(int fd, int spaces) const; String8 mName; @@ -106,7 +105,7 @@ private: static volatile int32_t mNextUniqueId; }; -class AudioPortConfig: public virtual RefBase +class AudioPortConfig : public virtual RefBase { public: AudioPortConfig(); diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h index 45e96d9..53cb4a3 100644 --- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h +++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h @@ -16,8 +16,16 @@ #pragma once +#include "DeviceDescriptor.h" +#include "HwModule.h" +#include "audio_policy_conf.h" #include -#include +#include +#include +#include +#include +#include +#include namespace android { @@ -161,6 +169,32 @@ public: static uint32_t parseOutputFlagNames(char *name); static uint32_t parseInputFlagNames(char *name); static audio_devices_t parseDeviceNames(char *name); + + static void loadHwModules(cnode *root, HwModuleCollection &hwModules, + DeviceVector &availableInputDevices, + DeviceVector &availableOutputDevices, + sp &defaultOutputDevices, + bool &isSpeakerDrcEnabled); + + static void loadGlobalConfig(cnode *root, const sp& module, + DeviceVector &availableInputDevices, + DeviceVector &availableOutputDevices, + sp &defaultOutputDevices, + bool &isSpeakerDrcEnabled); + + static status_t loadAudioPolicyConfig(const char *path, + HwModuleCollection &hwModules, + DeviceVector &availableInputDevices, + DeviceVector &availableOutputDevices, + sp &defaultOutputDevices, + bool &isSpeakerDrcEnabled); + +private: + static void loadHwModule(cnode *root, HwModuleCollection &hwModules, + DeviceVector &availableInputDevices, + DeviceVector &availableOutputDevices, + sp &defaultOutputDevices, + bool &isSpeakerDrcEnabled); }; }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h index e63ea2b..b9e1d4a 100644 --- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h @@ -22,10 +22,11 @@ #include #include #include +#include namespace android { -class DeviceDescriptor: public AudioPort, public AudioPortConfig +class DeviceDescriptor : public AudioPort, public AudioPortConfig { public: DeviceDescriptor(const String8& name, audio_devices_t type); @@ -43,12 +44,16 @@ public: virtual void loadGains(cnode *root); virtual void toAudioPort(struct audio_port *port) const; + audio_devices_t type() const { return mDeviceType; } status_t dump(int fd, int spaces, int index) const; - audio_devices_t mDeviceType; String8 mAddress; + audio_port_handle_t mId; static String8 emptyNameStr; + +private: + audio_devices_t mDeviceType; }; class DeviceVector : public SortedVector< sp > @@ -56,9 +61,9 @@ class DeviceVector : public SortedVector< sp > public: DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {} - ssize_t add(const sp& item); - ssize_t remove(const sp& item); - ssize_t indexOf(const sp& item) const; + ssize_t add(const sp& item); + ssize_t remove(const sp& item); + ssize_t indexOf(const sp& item) const; audio_devices_t types() const { return mDeviceTypes; } @@ -69,8 +74,13 @@ public: DeviceVector getDevicesFromType(audio_devices_t types) const; sp getDeviceFromId(audio_port_handle_t id) const; sp getDeviceFromName(const String8& name) const; - DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address) - const; + DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address) const; + + audio_devices_t getDevicesFromHwModule(audio_module_handle_t moduleHandle) const; + + audio_policy_dev_state_t getDeviceConnectionState(const sp &devDesc) const; + + status_t dump(int fd, const String8 &direction) const; private: void refreshTypes(); diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h index 3d4e2ad..92c3ea2 100644 --- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h +++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h @@ -45,6 +45,8 @@ public: audio_devices_t device, String8 address); status_t removeInputProfile(String8 name); + audio_module_handle_t getHandle() const { return mHandle; } + void dump(int fd); const char *const mName; // base name of the audio HW module (primary, a2dp ...) @@ -55,4 +57,18 @@ public: DeviceVector mDeclaredDevices; // devices declared in audio_policy.conf }; +class HwModuleCollection : public Vector< sp > +{ +public: + sp getModuleFromName(const char *name) const; + + sp getModuleForDevice(audio_devices_t device) const; + + sp getDeviceDescriptor(const audio_devices_t device, + const char *device_address, + const char *device_name) const; + + status_t dump(int fd) const; +}; + }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp index fa7761a..fa66728 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp @@ -22,6 +22,7 @@ #include "AudioGain.h" #include "HwModule.h" #include +#include namespace android { @@ -46,9 +47,13 @@ void AudioInputDescriptor::setIoHandle(audio_io_handle_t ioHandle) mIoHandle = ioHandle; } -void AudioInputDescriptor::toAudioPortConfig( - struct audio_port_config *dstConfig, - const struct audio_port_config *srcConfig) const +audio_module_handle_t AudioInputDescriptor::getModuleHandle() const +{ + return mProfile->getModuleHandle(); +} + +void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig, + const struct audio_port_config *srcConfig) const { ALOG_ASSERT(mProfile != 0, "toAudioPortConfig() called on input with null profile %d", mIoHandle); @@ -68,8 +73,7 @@ void AudioInputDescriptor::toAudioPortConfig( dstConfig->ext.mix.usecase.source = mInputSource; } -void AudioInputDescriptor::toAudioPort( - struct audio_port *port) const +void AudioInputDescriptor::toAudioPort(struct audio_port *port) const { ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle); @@ -107,4 +111,77 @@ status_t AudioInputDescriptor::dump(int fd) return NO_ERROR; } +bool AudioInputCollection::isSourceActive(audio_source_t source) const +{ + for (size_t i = 0; i < size(); i++) { + const sp inputDescriptor = valueAt(i); + if (inputDescriptor->mRefCount == 0) { + continue; + } + if (inputDescriptor->mInputSource == (int)source) { + return true; + } + } + return false; +} + +sp AudioInputCollection::getInputFromId(audio_port_handle_t id) const +{ + sp inputDesc = NULL; + for (size_t i = 0; i < size(); i++) { + inputDesc = valueAt(i); + if (inputDesc->mId == id) { + break; + } + } + return inputDesc; +} + +uint32_t AudioInputCollection::activeInputsCount() const +{ + uint32_t count = 0; + for (size_t i = 0; i < size(); i++) { + const sp desc = valueAt(i); + if (desc->mRefCount > 0) { + count++; + } + } + return count; +} + +audio_io_handle_t AudioInputCollection::getActiveInput(bool ignoreVirtualInputs) +{ + for (size_t i = 0; i < size(); i++) { + const sp input_descriptor = valueAt(i); + if ((input_descriptor->mRefCount > 0) + && (!ignoreVirtualInputs || !is_virtual_input_device(input_descriptor->mDevice))) { + return keyAt(i); + } + } + return 0; +} + +audio_devices_t AudioInputCollection::getSupportedDevices(audio_io_handle_t handle) const +{ + sp inputDesc = valueFor(handle); + audio_devices_t devices = inputDesc->mProfile->mSupportedDevices.types(); + return devices; +} + +status_t AudioInputCollection::dump(int fd) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + + snprintf(buffer, SIZE, "\nInputs dump:\n"); + write(fd, buffer, strlen(buffer)); + for (size_t i = 0; i < size(); i++) { + snprintf(buffer, SIZE, "- Input %d dump:\n", keyAt(i)); + write(fd, buffer, strlen(buffer)); + valueAt(i)->dump(fd); + } + + return NO_ERROR; +} + }; //namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index 4c5509d..cdb5b51 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -23,10 +23,13 @@ #include "HwModule.h" #include +// A device mask for all audio output devices that are considered "remote" when evaluating +// active output devices in isStreamActiveRemotely() +#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX + namespace android { -AudioOutputDescriptor::AudioOutputDescriptor( - const sp& profile) +AudioOutputDescriptor::AudioOutputDescriptor(const sp& profile) : mId(0), mIoHandle(0), mLatency(0), mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), mPatchHandle(0), @@ -53,6 +56,11 @@ AudioOutputDescriptor::AudioOutputDescriptor( } } +audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const +{ + return mProfile->getModuleHandle(); +} + audio_devices_t AudioOutputDescriptor::device() const { if (isDuplicated()) { @@ -134,8 +142,8 @@ bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const } bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, - uint32_t inPastMs, - nsecs_t sysTime) const + uint32_t inPastMs, + nsecs_t sysTime) const { if (mRefCount[stream] != 0) { return true; @@ -218,6 +226,108 @@ status_t AudioOutputDescriptor::dump(int fd) return NO_ERROR; } +bool AudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const +{ + nsecs_t sysTime = systemTime(); + for (size_t i = 0; i < this->size(); i++) { + const sp outputDesc = this->valueAt(i); + if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { + return true; + } + } + return false; +} + +bool AudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream, + uint32_t inPastMs) const +{ + nsecs_t sysTime = systemTime(); + for (size_t i = 0; i < size(); i++) { + const sp outputDesc = valueAt(i); + if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && + outputDesc->isStreamActive(stream, inPastMs, sysTime)) { + // do not consider re routing (when the output is going to a dynamic policy) + // as "remote playback" + if (outputDesc->mPolicyMix == NULL) { + return true; + } + } + } + return false; +} + +audio_io_handle_t AudioOutputCollection::getA2dpOutput() const +{ + for (size_t i = 0; i < size(); i++) { + sp outputDesc = valueAt(i); + if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { + return this->keyAt(i); + } + } + return 0; +} + +sp AudioOutputCollection::getPrimaryOutput() const +{ + for (size_t i = 0; i < size(); i++) { + const sp outputDesc = valueAt(i); + if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { + return outputDesc; + } + } + return NULL; +} +sp AudioOutputCollection::getOutputFromId(audio_port_handle_t id) const +{ + sp outputDesc = NULL; + for (size_t i = 0; i < size(); i++) { + outputDesc = valueAt(i); + if (outputDesc->mId == id) { + break; + } + } + return outputDesc; +} + +bool AudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const +{ + for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) { + if (s == (size_t) streamToIgnore) { + continue; + } + for (size_t i = 0; i < size(); i++) { + const sp outputDesc = valueAt(i); + if (outputDesc->mRefCount[s] != 0) { + return true; + } + } + } + return false; +} + +audio_devices_t AudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const +{ + sp outputDesc = valueFor(handle); + audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types(); + return devices; +} + + +status_t AudioOutputCollection::dump(int fd) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + + snprintf(buffer, SIZE, "\nOutputs dump:\n"); + write(fd, buffer, strlen(buffer)); + for (size_t i = 0; i < size(); i++) { + snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i)); + write(fd, buffer, strlen(buffer)); + valueAt(i)->dump(fd); + } + + return NO_ERROR; +} }; //namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp index 89e7f81..3a317fa 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp @@ -18,6 +18,7 @@ //#define LOG_NDEBUG 0 #include "AudioPatch.h" +#include "AudioGain.h" #include "ConfigParsingUtils.h" #include #include @@ -81,4 +82,73 @@ status_t AudioPatch::dump(int fd, int spaces, int index) const return NO_ERROR; } +status_t AudioPatchCollection::addAudioPatch(audio_patch_handle_t handle, + const sp& patch) +{ + ssize_t index = indexOfKey(handle); + + if (index >= 0) { + ALOGW("addAudioPatch() patch %d already in", handle); + return ALREADY_EXISTS; + } + add(handle, patch); + ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d" + "sink handle %d", + handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks, + patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id); + return NO_ERROR; +} + +status_t AudioPatchCollection::removeAudioPatch(audio_patch_handle_t handle) +{ + ssize_t index = indexOfKey(handle); + + if (index < 0) { + ALOGW("removeAudioPatch() patch %d not in", handle); + return ALREADY_EXISTS; + } + ALOGV("removeAudioPatch() handle %d af handle %d", handle, valueAt(index)->mAfPatchHandle); + removeItemsAt(index); + return NO_ERROR; +} + +status_t AudioPatchCollection::listAudioPatches(unsigned int *num_patches, + struct audio_patch *patches) const +{ + if (num_patches == NULL || (*num_patches != 0 && patches == NULL)) { + return BAD_VALUE; + } + ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu", + *num_patches, patches, size()); + if (patches == NULL) { + *num_patches = 0; + } + + size_t patchesWritten = 0; + size_t patchesMax = *num_patches; + for (size_t i = 0; i < size() && patchesWritten < patchesMax; i++) { + const sp patch = valueAt(i); + patches[patchesWritten] = patch->mPatch; + patches[patchesWritten++].id = patch->mHandle; + ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d", + i, patch->mPatch.num_sources, patch->mPatch.num_sinks); + } + *num_patches = size(); + + ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches); + return NO_ERROR; +} + +status_t AudioPatchCollection::dump(int fd) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + snprintf(buffer, SIZE, "\nAudio Patches:\n"); + write(fd, buffer, strlen(buffer)); + for (size_t i = 0; i < size(); i++) { + valueAt(i)->dump(fd, 2, i); + } + return NO_ERROR; +} + }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp index d34aac1..46a119e 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp @@ -22,6 +22,7 @@ #include "AudioGain.h" #include "ConfigParsingUtils.h" #include "audio_policy_conf.h" +#include namespace android { @@ -30,7 +31,7 @@ int32_t volatile AudioPort::mNextUniqueId = 1; // --- AudioPort class implementation AudioPort::AudioPort(const String8& name, audio_port_type_t type, - audio_port_role_t role, const sp& module) : + audio_port_role_t role, const sp& module) : mName(name), mType(type), mRole(role), mModule(module), mFlags(0), mId(0) { mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) || @@ -48,6 +49,11 @@ audio_port_handle_t AudioPort::getNextUniqueId() return static_cast(android_atomic_inc(&mNextUniqueId)); } +audio_module_handle_t AudioPort::getModuleHandle() const +{ + return mModule->mHandle; +} + void AudioPort::toAudioPort(struct audio_port *port) const { port->role = mRole; diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp index 300f35a..fe5bc5f 100644 --- a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp @@ -18,7 +18,10 @@ //#define LOG_NDEBUG 0 #include "ConfigParsingUtils.h" +#include "AudioGain.h" +#include #include +#include namespace android { @@ -119,4 +122,167 @@ audio_devices_t ConfigParsingUtils::parseDeviceNames(char *name) return device; } +//static +void ConfigParsingUtils::loadHwModule(cnode *root, HwModuleCollection &hwModules, + DeviceVector &availableInputDevices, + DeviceVector &availableOutputDevices, + sp &defaultOutputDevices, + bool &isSpeakerDrcEnable) +{ + status_t status = NAME_NOT_FOUND; + cnode *node; + sp module = new HwModule(root->name); + + node = config_find(root, DEVICES_TAG); + if (node != NULL) { + node = node->first_child; + while (node) { + ALOGV("loadHwModule() loading device %s", node->name); + status_t tmpStatus = module->loadDevice(node); + if (status == NAME_NOT_FOUND || status == NO_ERROR) { + status = tmpStatus; + } + node = node->next; + } + } + node = config_find(root, OUTPUTS_TAG); + if (node != NULL) { + node = node->first_child; + while (node) { + ALOGV("loadHwModule() loading output %s", node->name); + status_t tmpStatus = module->loadOutput(node); + if (status == NAME_NOT_FOUND || status == NO_ERROR) { + status = tmpStatus; + } + node = node->next; + } + } + node = config_find(root, INPUTS_TAG); + if (node != NULL) { + node = node->first_child; + while (node) { + ALOGV("loadHwModule() loading input %s", node->name); + status_t tmpStatus = module->loadInput(node); + if (status == NAME_NOT_FOUND || status == NO_ERROR) { + status = tmpStatus; + } + node = node->next; + } + } + loadGlobalConfig(root, module, availableInputDevices, availableOutputDevices, + defaultOutputDevices, isSpeakerDrcEnable); + + if (status == NO_ERROR) { + hwModules.add(module); + } +} + +//static +void ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules, + DeviceVector &availableInputDevices, + DeviceVector &availableOutputDevices, + sp &defaultOutputDevices, + bool &isSpeakerDrcEnabled) +{ + cnode *node = config_find(root, AUDIO_HW_MODULE_TAG); + if (node == NULL) { + return; + } + + node = node->first_child; + while (node) { + ALOGV("loadHwModules() loading module %s", node->name); + loadHwModule(node, hwModules, availableInputDevices, availableOutputDevices, + defaultOutputDevices, isSpeakerDrcEnabled); + node = node->next; + } +} + +//static +void ConfigParsingUtils::loadGlobalConfig(cnode *root, const sp& module, + DeviceVector &availableInputDevices, + DeviceVector &availableOutputDevices, + sp &defaultOutputDevice, + bool &speakerDrcEnabled) +{ + cnode *node = config_find(root, GLOBAL_CONFIG_TAG); + + if (node == NULL) { + return; + } + DeviceVector declaredDevices; + if (module != NULL) { + declaredDevices = module->mDeclaredDevices; + } + + node = node->first_child; + while (node) { + if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) { + availableOutputDevices.loadDevicesFromName((char *)node->value, + declaredDevices); + ALOGV("loadGlobalConfig() Attached Output Devices %08x", + availableOutputDevices.types()); + } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) { + audio_devices_t device = (audio_devices_t)stringToEnum( + sDeviceNameToEnumTable, + ARRAY_SIZE(sDeviceNameToEnumTable), + (char *)node->value); + if (device != AUDIO_DEVICE_NONE) { + defaultOutputDevice = new DeviceDescriptor(String8("default-output"), device); + } else { + ALOGW("loadGlobalConfig() default device not specified"); + } + ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type()); + } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) { + availableInputDevices.loadDevicesFromName((char *)node->value, + declaredDevices); + ALOGV("loadGlobalConfig() Available InputDevices %08x", availableInputDevices.types()); + } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) { + speakerDrcEnabled = stringToBool((char *)node->value); + ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", speakerDrcEnabled); + } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) { + uint32_t major, minor; + sscanf((char *)node->value, "%u.%u", &major, &minor); + module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor); + ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u", + module->mHalVersion, major, minor); + } + node = node->next; + } +} + +//static +status_t ConfigParsingUtils::loadAudioPolicyConfig(const char *path, + HwModuleCollection &hwModules, + DeviceVector &availableInputDevices, + DeviceVector &availableOutputDevices, + sp &defaultOutputDevices, + bool &isSpeakerDrcEnabled) +{ + cnode *root; + char *data; + + data = (char *)load_file(path, NULL); + if (data == NULL) { + return -ENODEV; + } + root = config_node("", ""); + config_load(root, data); + + loadHwModules(root, hwModules, + availableInputDevices, availableOutputDevices, + defaultOutputDevices, isSpeakerDrcEnabled); + // legacy audio_policy.conf files have one global_configuration section + loadGlobalConfig(root, hwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY), + availableInputDevices, availableOutputDevices, + defaultOutputDevices, isSpeakerDrcEnabled); + config_free(root); + free(root); + free(data); + + ALOGI("loadAudioPolicyConfig() loaded %s\n", path); + + return NO_ERROR; +} + }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp index 7f098ab..7df7d75 100644 --- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp @@ -27,11 +27,11 @@ namespace android { String8 DeviceDescriptor::emptyNameStr = String8(""); DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) : - AudioPort(name, AUDIO_PORT_TYPE_DEVICE, - audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : - AUDIO_PORT_ROLE_SOURCE, - NULL), - mDeviceType(type), mAddress("") + AudioPort(name, AUDIO_PORT_TYPE_DEVICE, + audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : + AUDIO_PORT_ROLE_SOURCE, + NULL), + mAddress(""), mDeviceType(type) { } @@ -60,7 +60,7 @@ void DeviceVector::refreshTypes() { mDeviceTypes = AUDIO_DEVICE_NONE; for(size_t i = 0; i < size(); i++) { - mDeviceTypes |= itemAt(i)->mDeviceType; + mDeviceTypes |= itemAt(i)->type(); } ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes); } @@ -85,7 +85,7 @@ ssize_t DeviceVector::add(const sp& item) refreshTypes(); } } else { - ALOGW("DeviceVector::add device %08x already in", item->mDeviceType); + ALOGW("DeviceVector::add device %08x already in", item->type()); ret = -1; } return ret; @@ -97,7 +97,7 @@ ssize_t DeviceVector::remove(const sp& item) ssize_t ret = indexOf(item); if (ret < 0) { - ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType); + ALOGW("DeviceVector::remove device %08x not in", item->type()); } else { ret = SortedVector::removeAt(ret); if (ret >= 0) { @@ -107,6 +107,17 @@ ssize_t DeviceVector::remove(const sp& item) return ret; } +audio_devices_t DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const +{ + audio_devices_t devices = AUDIO_DEVICE_NONE; + for (size_t i = 0; i < size(); i++) { + if (itemAt(i)->getModuleHandle() == moduleHandle) { + devices |= itemAt(i)->type(); + } + } + return devices; +} + void DeviceVector::loadDevicesFromType(audio_devices_t types) { DeviceVector deviceList; @@ -154,7 +165,7 @@ sp DeviceVector::getDevice(audio_devices_t type, String8 addre { sp device; for (size_t i = 0; i < size(); i++) { - if (itemAt(i)->mDeviceType == type) { + if (itemAt(i)->type() == type) { if (address == "" || itemAt(i)->mAddress == address) { device = itemAt(i); if (itemAt(i)->mAddress == address) { @@ -192,7 +203,7 @@ DeviceVector DeviceVector::getDevicesFromType(audio_devices_t type) const devices.add(itemAt(i)); type &= ~curType; ALOGV("DeviceVector::getDevicesFromType() for type %x found %p", - itemAt(i)->mDeviceType, itemAt(i).get()); + itemAt(i)->type(), itemAt(i).get()); } } return devices; @@ -203,7 +214,7 @@ DeviceVector DeviceVector::getDevicesFromTypeAddr( { DeviceVector devices; for (size_t i = 0; i < size(); i++) { - if (itemAt(i)->mDeviceType == type) { + if (itemAt(i)->type() == type) { if (itemAt(i)->mAddress == address) { devices.add(itemAt(i)); } @@ -224,6 +235,26 @@ sp DeviceVector::getDeviceFromName(const String8& name) const return device; } + +status_t DeviceVector::dump(int fd, const String8 &direction) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + + snprintf(buffer, SIZE, "\n Available %s devices:\n", direction.string()); + write(fd, buffer, strlen(buffer)); + for (size_t i = 0; i < size(); i++) { + itemAt(i)->dump(fd, 2, i); + } + return NO_ERROR; +} + +audio_policy_dev_state_t DeviceVector::getDeviceConnectionState(const sp &devDesc) const +{ + ssize_t index = indexOf(devDesc); + return index >= 0 ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; +} + void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig) const { diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp index a0ea185..8004303 100644 --- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp @@ -23,6 +23,7 @@ #include "ConfigParsingUtils.h" #include "audio_policy_conf.h" #include +#include namespace android { @@ -279,4 +280,92 @@ void HwModule::dump(int fd) } } +sp HwModuleCollection::getModuleFromName(const char *name) const +{ + sp module; + + for (size_t i = 0; i < size(); i++) + { + if (strcmp(itemAt(i)->mName, name) == 0) { + return itemAt(i); + } + } + return module; +} + + +sp HwModuleCollection::getModuleForDevice(audio_devices_t device) const +{ + sp module; + + for (size_t i = 0; i < size(); i++) { + if (itemAt(i)->mHandle == 0) { + continue; + } + if (audio_is_output_device(device)) { + for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++) + { + if (itemAt(i)->mOutputProfiles[j]->mSupportedDevices.types() & device) { + return itemAt(i); + } + } + } else { + for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) { + if (itemAt(i)->mInputProfiles[j]->mSupportedDevices.types() & + device & ~AUDIO_DEVICE_BIT_IN) { + return itemAt(i); + } + } + } + } + return module; +} + +sp HwModuleCollection::getDeviceDescriptor(const audio_devices_t device, + const char *device_address, + const char *device_name) const +{ + String8 address = (device_address == NULL) ? String8("") : String8(device_address); + // handle legacy remote submix case where the address was not always specified + if (device_distinguishes_on_address(device) && (address.length() == 0)) { + address = String8("0"); + } + + for (size_t i = 0; i < size(); i++) { + const sp hwModule = itemAt(i); + if (hwModule->mHandle == 0) { + continue; + } + DeviceVector deviceList = + hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address); + if (!deviceList.isEmpty()) { + return deviceList.itemAt(0); + } + deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device); + if (!deviceList.isEmpty()) { + return deviceList.itemAt(0); + } + } + + sp devDesc = + new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device); + devDesc->mAddress = address; + return devDesc; +} + +status_t HwModuleCollection::dump(int fd) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + + snprintf(buffer, SIZE, "\nHW Modules dump:\n"); + write(fd, buffer, strlen(buffer)); + for (size_t i = 0; i < size(); i++) { + snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1); + write(fd, buffer, strlen(buffer)); + itemAt(i)->dump(fd); + } + return NO_ERROR; +} + } //namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp index 0214a2b..376dd22 100644 --- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp @@ -37,12 +37,12 @@ IOProfile::~IOProfile() // Sampling rate, format and channel mask must be specified in order to // get a valid a match bool IOProfile::isCompatibleProfile(audio_devices_t device, - String8 address, - uint32_t samplingRate, - uint32_t *updatedSamplingRate, - audio_format_t format, - audio_channel_mask_t channelMask, - uint32_t flags) const + String8 address, + uint32_t samplingRate, + uint32_t *updatedSamplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + uint32_t flags) const { const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE; const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK; -- cgit v1.1