Loading services/audiopolicy/common/managerdefinitions/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ LOCAL_SRC_FILES:= \ src/HwModule.cpp \ src/IOProfile.cpp \ src/AudioPort.cpp \ src/AudioPolicyMix.cpp \ src/AudioPatch.cpp \ src/AudioInputDescriptor.cpp \ src/AudioOutputDescriptor.cpp \ Loading services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * 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 <utils/RefBase.h> #include <media/AudioPolicy.h> #include <utils/KeyedVector.h> #include <hardware/audio.h> #include <utils/String8.h> namespace android { class AudioOutputDescriptor; /** * custom mix entry in mPolicyMixes */ class AudioPolicyMix : public RefBase { public: AudioPolicyMix() {} const sp<AudioOutputDescriptor> &getOutput() const; void setOutput(sp<AudioOutputDescriptor> &output); void clearOutput(); android::AudioMix &getMix(); void setMix(AudioMix &mix); private: AudioMix mMix; // Audio policy mix descriptor sp<AudioOutputDescriptor> mOutput; // Corresponding output stream }; class AudioPolicyMixCollection : public DefaultKeyedVector<String8, sp<AudioPolicyMix> > { public: status_t getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const; status_t registerMix(String8 address, AudioMix mix); status_t unregisterMix(String8 address); void closeOutput(sp<AudioOutputDescriptor> &desc); /** * Try to find an output descriptor for the given attributes. * * @param[in] attributes to consider for the research of output descriptor. * @param[out] desc to return if an output could be found. * * @return NO_ERROR if an output was found for the given attribute (in this case, the * descriptor output param is initialized), error code otherwise. */ status_t getOutputForAttr(audio_attributes_t attributes, sp<AudioOutputDescriptor> &desc); audio_devices_t getDeviceAndMixForInputSource(audio_source_t inputSource, audio_devices_t availableDeviceTypes, AudioMix **policyMix); status_t getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix); }; }; // namespace android services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp 0 → 100644 +193 −0 Original line number Diff line number Diff line /* * 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. */ #define LOG_TAG "APM::AudioPolicyMix" //#define LOG_NDEBUG 0 #include "AudioPolicyMix.h" #include "HwModule.h" #include "AudioPort.h" #include "IOProfile.h" #include "AudioGain.h" #include <AudioOutputDescriptor.h> namespace android { void AudioPolicyMix::setOutput(sp<AudioOutputDescriptor> &output) { mOutput = output; } const sp<AudioOutputDescriptor> &AudioPolicyMix::getOutput() const { return mOutput; } void AudioPolicyMix::clearOutput() { mOutput.clear(); } void AudioPolicyMix::setMix(AudioMix &mix) { mMix = mix; } android::AudioMix &AudioPolicyMix::getMix() { return mMix; } status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix) { ssize_t index = indexOfKey(address); if (index >= 0) { ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string()); return BAD_VALUE; } sp<AudioPolicyMix> policyMix = new AudioPolicyMix(); policyMix->setMix(mix); add(address, policyMix); return NO_ERROR; } status_t AudioPolicyMixCollection::unregisterMix(String8 address) { ssize_t index = indexOfKey(address); if (index < 0) { ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); return BAD_VALUE; } removeItemsAt(index); return NO_ERROR; } status_t AudioPolicyMixCollection::getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const { ssize_t index = indexOfKey(address); if (index < 0) { ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); return BAD_VALUE; } policyMix = valueAt(index); return NO_ERROR; } void AudioPolicyMixCollection::closeOutput(sp<AudioOutputDescriptor> &desc) { for (size_t i = 0; i < size(); i++) { sp<AudioPolicyMix> policyMix = valueAt(i); if (policyMix->getOutput() == desc) { policyMix->clearOutput(); } } } status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes, sp<AudioOutputDescriptor> &desc) { for (size_t i = 0; i < size(); i++) { sp<AudioPolicyMix> policyMix = valueAt(i); AudioMix mix = policyMix->getMix(); if (mix.mMixType == MIX_TYPE_PLAYERS) { for (size_t j = 0; j < mix.mCriteria.size(); j++) { if ((RULE_MATCH_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule && mix.mCriteria[j].mAttr.mUsage == attributes.usage) || (RULE_EXCLUDE_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule && mix.mCriteria[j].mAttr.mUsage != attributes.usage)) { desc = policyMix->getOutput(); break; } if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && strncmp(attributes.tags + strlen("addr="), mix.mRegistrationId.string(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { desc = policyMix->getOutput(); break; } } } else if (mix.mMixType == MIX_TYPE_RECORDERS) { if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE && strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && strncmp(attributes.tags + strlen("addr="), mix.mRegistrationId.string(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { desc = policyMix->getOutput(); } } if (desc != 0) { desc->mPolicyMix = &mix; return NO_ERROR; } } return BAD_VALUE; } audio_devices_t AudioPolicyMixCollection::getDeviceAndMixForInputSource(audio_source_t inputSource, audio_devices_t availDevices, AudioMix **policyMix) { for (size_t i = 0; i < size(); i++) { AudioMix mix = valueAt(i)->getMix(); if (mix.mMixType != MIX_TYPE_RECORDERS) { continue; } for (size_t j = 0; j < mix.mCriteria.size(); j++) { if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule && mix.mCriteria[j].mAttr.mSource == inputSource) || (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule && mix.mCriteria[j].mAttr.mSource != inputSource)) { if (availDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { if (policyMix != NULL) { *policyMix = &mix; } return AUDIO_DEVICE_IN_REMOTE_SUBMIX; } break; } } } return AUDIO_DEVICE_NONE; } status_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix) { if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) { return BAD_VALUE; } String8 address(attr.tags + strlen("addr=")); ssize_t index = indexOfKey(address); if (index < 0) { ALOGW("getInputForAttr() no policy for address %s", address.string()); return BAD_VALUE; } sp<AudioPolicyMix> audioPolicyMix = valueAt(index); AudioMix mix = audioPolicyMix->getMix(); if (mix.mMixType != MIX_TYPE_PLAYERS) { ALOGW("getInputForAttr() bad policy mix type for address %s", address.string()); return BAD_VALUE; } policyMix = &mix; return NO_ERROR; } }; //namespace android services/audiopolicy/managerdefault/AudioPolicyManager.cpp +30 −92 Original line number Diff line number Diff line Loading @@ -707,46 +707,17 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, } stream_type_to_audio_attributes(*stream, &attributes); } for (size_t i = 0; i < mPolicyMixes.size(); i++) { sp<AudioOutputDescriptor> desc; if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_PLAYERS) { for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) { if ((RULE_MATCH_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule && mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage == attributes.usage) || (RULE_EXCLUDE_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule && mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage != attributes.usage)) { desc = mPolicyMixes[i]->mOutput; break; } if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && strncmp(attributes.tags + strlen("addr="), mPolicyMixes[i]->mMix.mRegistrationId.string(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { desc = mPolicyMixes[i]->mOutput; break; } } } else if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_RECORDERS) { if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE && strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && strncmp(attributes.tags + strlen("addr="), mPolicyMixes[i]->mMix.mRegistrationId.string(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { desc = mPolicyMixes[i]->mOutput; } } if (desc != 0) { if (mPolicyMixes.getOutputForAttr(attributes, desc) == NO_ERROR) { ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr"); if (!audio_is_linear_pcm(format)) { return BAD_VALUE; } desc->mPolicyMix = &mPolicyMixes[i]->mMix; *stream = streamTypefromAttributesInt(&attributes); *output = desc->mIoHandle; ALOGV("getOutputForAttr() returns output %d", *output); return NO_ERROR; } } if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) { ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE"); return BAD_VALUE; Loading Loading @@ -1286,19 +1257,13 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX && strncmp(attr->tags, "addr=", strlen("addr=")) == 0) { device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; address = String8(attr->tags + strlen("addr=")); ssize_t index = mPolicyMixes.indexOfKey(address); if (index < 0) { ALOGW("getInputForAttr() no policy for address %s", address.string()); return BAD_VALUE; status_t ret = mPolicyMixes.getInputMixForAttr(*attr, policyMix); if (ret != NO_ERROR) { return ret; } if (mPolicyMixes[index]->mMix.mMixType != MIX_TYPE_PLAYERS) { ALOGW("getInputForAttr() bad policy mix type for address %s", address.string()); return BAD_VALUE; } policyMix = &mPolicyMixes[index]->mMix; *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE; device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; address = String8(attr->tags + strlen("addr=")); } else { device = getDeviceAndMixForInputSource(inputSource, &policyMix); if (device == AUDIO_DEVICE_NONE) { Loading Loading @@ -1929,9 +1894,8 @@ status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes) for (size_t i = 0; i < mixes.size(); i++) { String8 address = mixes[i].mRegistrationId; ssize_t index = mPolicyMixes.indexOfKey(address); if (index >= 0) { ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string()); if (mPolicyMixes.registerMix(address, mixes[i]) != NO_ERROR) { continue; } audio_config_t outputConfig = mixes[i].mFormat; Loading @@ -1944,9 +1908,7 @@ status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes) AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address); module->addInputProfile(address, &inputConfig, AUDIO_DEVICE_IN_REMOTE_SUBMIX, address); sp<AudioPolicyMix> policyMix = new AudioPolicyMix(); policyMix->mMix = mixes[i]; mPolicyMixes.add(address, policyMix); if (mixes[i].mMixType == MIX_TYPE_PLAYERS) { setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_POLICY_DEVICE_STATE_AVAILABLE, Loading Loading @@ -1979,14 +1941,11 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes) for (size_t i = 0; i < mixes.size(); i++) { String8 address = mixes[i].mRegistrationId; ssize_t index = mPolicyMixes.indexOfKey(address); if (index < 0) { ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); if (mPolicyMixes.unregisterMix(address) != NO_ERROR) { continue; } mPolicyMixes.removeItemsAt(index); if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { Loading Loading @@ -3261,14 +3220,14 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de if (output != AUDIO_IO_HANDLE_NONE) { addOutput(output, desc); if (device_distinguishes_on_address(device) && address != "0") { ssize_t index = mPolicyMixes.indexOfKey(address); if (index >= 0) { mPolicyMixes[index]->mOutput = desc; desc->mPolicyMix = &mPolicyMixes[index]->mMix; } else { sp<AudioPolicyMix> policyMix; if (mPolicyMixes.getAudioPolicyMix(address, policyMix) != NO_ERROR) { ALOGE("checkOutputsForDevice() cannot find policy for address %s", address.string()); } policyMix->setOutput(desc); desc->mPolicyMix = &(policyMix->getMix()); } else if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) { // no duplicated output for direct outputs and // outputs used by dynamic policy mixes Loading Loading @@ -3579,12 +3538,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output) ALOGW("closeOutput() unknown output %d", output); return; } for (size_t i = 0; i < mPolicyMixes.size(); i++) { if (mPolicyMixes[i]->mOutput == outputDesc) { mPolicyMixes[i]->mOutput.clear(); } } mPolicyMixes.closeOutput(outputDesc); // look for duplicated outputs connected to the output being removed. for (size_t i = 0; i < mOutputs.size(); i++) { Loading Loading @@ -4730,29 +4684,13 @@ sp<IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device, audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource, AudioMix **policyMix) { audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; audio_devices_t selectedDeviceFromMix = mPolicyMixes.getDeviceAndMixForInputSource(inputSource, availableDeviceTypes, policyMix); for (size_t i = 0; i < mPolicyMixes.size(); i++) { if (mPolicyMixes[i]->mMix.mMixType != MIX_TYPE_RECORDERS) { continue; } for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) { if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule && mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource == inputSource) || (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule && mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource != inputSource)) { if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { if (policyMix != NULL) { *policyMix = &mPolicyMixes[i]->mMix; } return AUDIO_DEVICE_IN_REMOTE_SUBMIX; if (selectedDeviceFromMix != AUDIO_DEVICE_NONE) { return selectedDeviceFromMix; } break; } } } return getDeviceForInputSource(inputSource); } Loading services/audiopolicy/managerdefault/AudioPolicyManager.h +2 −10 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include <HwModule.h> #include <AudioInputDescriptor.h> #include <AudioOutputDescriptor.h> #include <AudioPolicyMix.h> namespace android { Loading Loading @@ -474,16 +475,7 @@ protected: uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams bool mBeaconMuted; // has STREAM_TTS been muted // custom mix entry in mPolicyMixes class AudioPolicyMix : public RefBase { public: AudioPolicyMix() {} AudioMix mMix; // Audio policy mix descriptor sp<AudioOutputDescriptor> mOutput; // Corresponding output stream }; DefaultKeyedVector<String8, sp<AudioPolicyMix> > mPolicyMixes; // list of registered mixes AudioPolicyMixCollection mPolicyMixes; // list of registered mixes #ifdef AUDIO_POLICY_TEST Mutex mLock; Loading Loading
services/audiopolicy/common/managerdefinitions/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ LOCAL_SRC_FILES:= \ src/HwModule.cpp \ src/IOProfile.cpp \ src/AudioPort.cpp \ src/AudioPolicyMix.cpp \ src/AudioPatch.cpp \ src/AudioInputDescriptor.cpp \ src/AudioOutputDescriptor.cpp \ Loading
services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * 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 <utils/RefBase.h> #include <media/AudioPolicy.h> #include <utils/KeyedVector.h> #include <hardware/audio.h> #include <utils/String8.h> namespace android { class AudioOutputDescriptor; /** * custom mix entry in mPolicyMixes */ class AudioPolicyMix : public RefBase { public: AudioPolicyMix() {} const sp<AudioOutputDescriptor> &getOutput() const; void setOutput(sp<AudioOutputDescriptor> &output); void clearOutput(); android::AudioMix &getMix(); void setMix(AudioMix &mix); private: AudioMix mMix; // Audio policy mix descriptor sp<AudioOutputDescriptor> mOutput; // Corresponding output stream }; class AudioPolicyMixCollection : public DefaultKeyedVector<String8, sp<AudioPolicyMix> > { public: status_t getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const; status_t registerMix(String8 address, AudioMix mix); status_t unregisterMix(String8 address); void closeOutput(sp<AudioOutputDescriptor> &desc); /** * Try to find an output descriptor for the given attributes. * * @param[in] attributes to consider for the research of output descriptor. * @param[out] desc to return if an output could be found. * * @return NO_ERROR if an output was found for the given attribute (in this case, the * descriptor output param is initialized), error code otherwise. */ status_t getOutputForAttr(audio_attributes_t attributes, sp<AudioOutputDescriptor> &desc); audio_devices_t getDeviceAndMixForInputSource(audio_source_t inputSource, audio_devices_t availableDeviceTypes, AudioMix **policyMix); status_t getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix); }; }; // namespace android
services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp 0 → 100644 +193 −0 Original line number Diff line number Diff line /* * 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. */ #define LOG_TAG "APM::AudioPolicyMix" //#define LOG_NDEBUG 0 #include "AudioPolicyMix.h" #include "HwModule.h" #include "AudioPort.h" #include "IOProfile.h" #include "AudioGain.h" #include <AudioOutputDescriptor.h> namespace android { void AudioPolicyMix::setOutput(sp<AudioOutputDescriptor> &output) { mOutput = output; } const sp<AudioOutputDescriptor> &AudioPolicyMix::getOutput() const { return mOutput; } void AudioPolicyMix::clearOutput() { mOutput.clear(); } void AudioPolicyMix::setMix(AudioMix &mix) { mMix = mix; } android::AudioMix &AudioPolicyMix::getMix() { return mMix; } status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix) { ssize_t index = indexOfKey(address); if (index >= 0) { ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string()); return BAD_VALUE; } sp<AudioPolicyMix> policyMix = new AudioPolicyMix(); policyMix->setMix(mix); add(address, policyMix); return NO_ERROR; } status_t AudioPolicyMixCollection::unregisterMix(String8 address) { ssize_t index = indexOfKey(address); if (index < 0) { ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); return BAD_VALUE; } removeItemsAt(index); return NO_ERROR; } status_t AudioPolicyMixCollection::getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const { ssize_t index = indexOfKey(address); if (index < 0) { ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); return BAD_VALUE; } policyMix = valueAt(index); return NO_ERROR; } void AudioPolicyMixCollection::closeOutput(sp<AudioOutputDescriptor> &desc) { for (size_t i = 0; i < size(); i++) { sp<AudioPolicyMix> policyMix = valueAt(i); if (policyMix->getOutput() == desc) { policyMix->clearOutput(); } } } status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes, sp<AudioOutputDescriptor> &desc) { for (size_t i = 0; i < size(); i++) { sp<AudioPolicyMix> policyMix = valueAt(i); AudioMix mix = policyMix->getMix(); if (mix.mMixType == MIX_TYPE_PLAYERS) { for (size_t j = 0; j < mix.mCriteria.size(); j++) { if ((RULE_MATCH_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule && mix.mCriteria[j].mAttr.mUsage == attributes.usage) || (RULE_EXCLUDE_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule && mix.mCriteria[j].mAttr.mUsage != attributes.usage)) { desc = policyMix->getOutput(); break; } if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && strncmp(attributes.tags + strlen("addr="), mix.mRegistrationId.string(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { desc = policyMix->getOutput(); break; } } } else if (mix.mMixType == MIX_TYPE_RECORDERS) { if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE && strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && strncmp(attributes.tags + strlen("addr="), mix.mRegistrationId.string(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { desc = policyMix->getOutput(); } } if (desc != 0) { desc->mPolicyMix = &mix; return NO_ERROR; } } return BAD_VALUE; } audio_devices_t AudioPolicyMixCollection::getDeviceAndMixForInputSource(audio_source_t inputSource, audio_devices_t availDevices, AudioMix **policyMix) { for (size_t i = 0; i < size(); i++) { AudioMix mix = valueAt(i)->getMix(); if (mix.mMixType != MIX_TYPE_RECORDERS) { continue; } for (size_t j = 0; j < mix.mCriteria.size(); j++) { if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule && mix.mCriteria[j].mAttr.mSource == inputSource) || (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule && mix.mCriteria[j].mAttr.mSource != inputSource)) { if (availDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { if (policyMix != NULL) { *policyMix = &mix; } return AUDIO_DEVICE_IN_REMOTE_SUBMIX; } break; } } } return AUDIO_DEVICE_NONE; } status_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix) { if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) { return BAD_VALUE; } String8 address(attr.tags + strlen("addr=")); ssize_t index = indexOfKey(address); if (index < 0) { ALOGW("getInputForAttr() no policy for address %s", address.string()); return BAD_VALUE; } sp<AudioPolicyMix> audioPolicyMix = valueAt(index); AudioMix mix = audioPolicyMix->getMix(); if (mix.mMixType != MIX_TYPE_PLAYERS) { ALOGW("getInputForAttr() bad policy mix type for address %s", address.string()); return BAD_VALUE; } policyMix = &mix; return NO_ERROR; } }; //namespace android
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +30 −92 Original line number Diff line number Diff line Loading @@ -707,46 +707,17 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, } stream_type_to_audio_attributes(*stream, &attributes); } for (size_t i = 0; i < mPolicyMixes.size(); i++) { sp<AudioOutputDescriptor> desc; if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_PLAYERS) { for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) { if ((RULE_MATCH_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule && mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage == attributes.usage) || (RULE_EXCLUDE_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule && mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage != attributes.usage)) { desc = mPolicyMixes[i]->mOutput; break; } if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && strncmp(attributes.tags + strlen("addr="), mPolicyMixes[i]->mMix.mRegistrationId.string(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { desc = mPolicyMixes[i]->mOutput; break; } } } else if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_RECORDERS) { if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE && strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && strncmp(attributes.tags + strlen("addr="), mPolicyMixes[i]->mMix.mRegistrationId.string(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { desc = mPolicyMixes[i]->mOutput; } } if (desc != 0) { if (mPolicyMixes.getOutputForAttr(attributes, desc) == NO_ERROR) { ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr"); if (!audio_is_linear_pcm(format)) { return BAD_VALUE; } desc->mPolicyMix = &mPolicyMixes[i]->mMix; *stream = streamTypefromAttributesInt(&attributes); *output = desc->mIoHandle; ALOGV("getOutputForAttr() returns output %d", *output); return NO_ERROR; } } if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) { ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE"); return BAD_VALUE; Loading Loading @@ -1286,19 +1257,13 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX && strncmp(attr->tags, "addr=", strlen("addr=")) == 0) { device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; address = String8(attr->tags + strlen("addr=")); ssize_t index = mPolicyMixes.indexOfKey(address); if (index < 0) { ALOGW("getInputForAttr() no policy for address %s", address.string()); return BAD_VALUE; status_t ret = mPolicyMixes.getInputMixForAttr(*attr, policyMix); if (ret != NO_ERROR) { return ret; } if (mPolicyMixes[index]->mMix.mMixType != MIX_TYPE_PLAYERS) { ALOGW("getInputForAttr() bad policy mix type for address %s", address.string()); return BAD_VALUE; } policyMix = &mPolicyMixes[index]->mMix; *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE; device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; address = String8(attr->tags + strlen("addr=")); } else { device = getDeviceAndMixForInputSource(inputSource, &policyMix); if (device == AUDIO_DEVICE_NONE) { Loading Loading @@ -1929,9 +1894,8 @@ status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes) for (size_t i = 0; i < mixes.size(); i++) { String8 address = mixes[i].mRegistrationId; ssize_t index = mPolicyMixes.indexOfKey(address); if (index >= 0) { ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string()); if (mPolicyMixes.registerMix(address, mixes[i]) != NO_ERROR) { continue; } audio_config_t outputConfig = mixes[i].mFormat; Loading @@ -1944,9 +1908,7 @@ status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes) AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address); module->addInputProfile(address, &inputConfig, AUDIO_DEVICE_IN_REMOTE_SUBMIX, address); sp<AudioPolicyMix> policyMix = new AudioPolicyMix(); policyMix->mMix = mixes[i]; mPolicyMixes.add(address, policyMix); if (mixes[i].mMixType == MIX_TYPE_PLAYERS) { setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_POLICY_DEVICE_STATE_AVAILABLE, Loading Loading @@ -1979,14 +1941,11 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes) for (size_t i = 0; i < mixes.size(); i++) { String8 address = mixes[i].mRegistrationId; ssize_t index = mPolicyMixes.indexOfKey(address); if (index < 0) { ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); if (mPolicyMixes.unregisterMix(address) != NO_ERROR) { continue; } mPolicyMixes.removeItemsAt(index); if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { Loading Loading @@ -3261,14 +3220,14 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de if (output != AUDIO_IO_HANDLE_NONE) { addOutput(output, desc); if (device_distinguishes_on_address(device) && address != "0") { ssize_t index = mPolicyMixes.indexOfKey(address); if (index >= 0) { mPolicyMixes[index]->mOutput = desc; desc->mPolicyMix = &mPolicyMixes[index]->mMix; } else { sp<AudioPolicyMix> policyMix; if (mPolicyMixes.getAudioPolicyMix(address, policyMix) != NO_ERROR) { ALOGE("checkOutputsForDevice() cannot find policy for address %s", address.string()); } policyMix->setOutput(desc); desc->mPolicyMix = &(policyMix->getMix()); } else if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) { // no duplicated output for direct outputs and // outputs used by dynamic policy mixes Loading Loading @@ -3579,12 +3538,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output) ALOGW("closeOutput() unknown output %d", output); return; } for (size_t i = 0; i < mPolicyMixes.size(); i++) { if (mPolicyMixes[i]->mOutput == outputDesc) { mPolicyMixes[i]->mOutput.clear(); } } mPolicyMixes.closeOutput(outputDesc); // look for duplicated outputs connected to the output being removed. for (size_t i = 0; i < mOutputs.size(); i++) { Loading Loading @@ -4730,29 +4684,13 @@ sp<IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device, audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource, AudioMix **policyMix) { audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; audio_devices_t selectedDeviceFromMix = mPolicyMixes.getDeviceAndMixForInputSource(inputSource, availableDeviceTypes, policyMix); for (size_t i = 0; i < mPolicyMixes.size(); i++) { if (mPolicyMixes[i]->mMix.mMixType != MIX_TYPE_RECORDERS) { continue; } for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) { if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule && mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource == inputSource) || (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule && mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource != inputSource)) { if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { if (policyMix != NULL) { *policyMix = &mPolicyMixes[i]->mMix; } return AUDIO_DEVICE_IN_REMOTE_SUBMIX; if (selectedDeviceFromMix != AUDIO_DEVICE_NONE) { return selectedDeviceFromMix; } break; } } } return getDeviceForInputSource(inputSource); } Loading
services/audiopolicy/managerdefault/AudioPolicyManager.h +2 −10 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include <HwModule.h> #include <AudioInputDescriptor.h> #include <AudioOutputDescriptor.h> #include <AudioPolicyMix.h> namespace android { Loading Loading @@ -474,16 +475,7 @@ protected: uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams bool mBeaconMuted; // has STREAM_TTS been muted // custom mix entry in mPolicyMixes class AudioPolicyMix : public RefBase { public: AudioPolicyMix() {} AudioMix mMix; // Audio policy mix descriptor sp<AudioOutputDescriptor> mOutput; // Corresponding output stream }; DefaultKeyedVector<String8, sp<AudioPolicyMix> > mPolicyMixes; // list of registered mixes AudioPolicyMixCollection mPolicyMixes; // list of registered mixes #ifdef AUDIO_POLICY_TEST Mutex mLock; Loading