Merge changes I05611b70,I6cd1a53e,Ic2e08efc,I13ac0673,I0d87fd76 am: 1e415c058a

am: 7cde662ae3

Change-Id: I00be2cf94686e70ec45038c05767188f96659308
gugelfrei
jiabin 5 years ago committed by android-build-merger
commit f1e48f349f

@ -10,17 +10,21 @@ cc_library_shared {
srcs: [ srcs: [
"AudioGain.cpp", "AudioGain.cpp",
"AudioPortBase.cpp",
"AudioProfile.cpp",
], ],
shared_libs: [ shared_libs: [
"libbase", "libbase",
"libbinder", "libbinder",
"liblog", "liblog",
"libmedia_helper",
"libutils", "libutils",
], ],
header_libs: [ header_libs: [
"libaudio_system_headers", "libaudio_system_headers",
"libaudioclient_headers",
"libaudiofoundation_headers", "libaudiofoundation_headers",
], ],

@ -0,0 +1,87 @@
/*
* Copyright (C) 2019 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.
*/
#include <algorithm>
#include <android-base/stringprintf.h>
#include <media/AudioPortBase.h>
#include <utils/Log.h>
namespace android {
void AudioPortFoundation::toAudioPort(struct audio_port *port) const {
// TODO: update this function once audio_port structure reflects the new profile definition.
// For compatibility reason: flatening the AudioProfile into audio_port structure.
FormatSet flatenedFormats;
SampleRateSet flatenedRates;
ChannelMaskSet flatenedChannels;
for (const auto& profile : *getAudioProfileVectorBase()) {
if (profile->isValid()) {
audio_format_t formatToExport = profile->getFormat();
const SampleRateSet &ratesToExport = profile->getSampleRates();
const ChannelMaskSet &channelsToExport = profile->getChannels();
flatenedFormats.insert(formatToExport);
flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());
if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
ALOGE("%s: bailing out: cannot export profiles to port config", __func__);
return;
}
}
}
port->role = mRole;
port->type = mType;
strlcpy(port->name, mName.c_str(), AUDIO_PORT_MAX_NAME_LEN);
port->num_sample_rates = flatenedRates.size();
port->num_channel_masks = flatenedChannels.size();
port->num_formats = flatenedFormats.size();
std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);
ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS);
for (size_t i = 0; i < port->num_gains; i++) {
port->gains[i] = mGains[i]->getGain();
}
}
void AudioPortFoundation::dump(std::string *dst, int spaces, bool verbose) const {
if (!mName.empty()) {
dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
}
if (verbose) {
std::string profilesStr;
getAudioProfileVectorBase()->dump(&profilesStr, spaces);
dst->append(profilesStr);
if (mGains.size() != 0) {
dst->append(base::StringPrintf("%*s- gains:\n", spaces, ""));
for (size_t i = 0; i < mGains.size(); i++) {
std::string gainStr;
mGains[i]->dump(&gainStr, spaces + 2, i);
dst->append(gainStr);
}
}
}
}
}

@ -0,0 +1,222 @@
/*
* 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.
*/
#include <set>
#define LOG_TAG "AudioProfile"
//#define LOG_NDEBUG 0
#include <android-base/stringprintf.h>
#include <media/AudioContainers.h>
#include <media/AudioProfile.h>
#include <media/TypeConverter.h>
#include <utils/Errors.h>
namespace android {
bool operator == (const AudioProfile &left, const AudioProfile &right)
{
return (left.getFormat() == right.getFormat()) &&
(left.getChannels() == right.getChannels()) &&
(left.getSampleRates() == right.getSampleRates());
}
// static
sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat)
{
AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat,
ChannelMaskSet(), SampleRateSet());
dynamicProfile->setDynamicFormat(true);
dynamicProfile->setDynamicChannels(true);
dynamicProfile->setDynamicRate(true);
return dynamicProfile;
}
AudioProfile::AudioProfile(audio_format_t format,
audio_channel_mask_t channelMasks,
uint32_t samplingRate) :
mName(""),
mFormat(format)
{
mChannelMasks.insert(channelMasks);
mSamplingRates.insert(samplingRate);
}
AudioProfile::AudioProfile(audio_format_t format,
const ChannelMaskSet &channelMasks,
const SampleRateSet &samplingRateCollection) :
mName(""),
mFormat(format),
mChannelMasks(channelMasks),
mSamplingRates(samplingRateCollection) {}
void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
{
if (mIsDynamicChannels) {
mChannelMasks = channelMasks;
}
}
void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
{
if (mIsDynamicRate) {
mSamplingRates = sampleRates;
}
}
void AudioProfile::clear()
{
if (mIsDynamicChannels) {
mChannelMasks.clear();
}
if (mIsDynamicRate) {
mSamplingRates.clear();
}
}
void AudioProfile::dump(std::string *dst, int spaces) const
{
dst->append(base::StringPrintf("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
mIsDynamicChannels ? "[dynamic channels]" : "",
mIsDynamicRate ? "[dynamic rates]" : ""));
if (mName.length() != 0) {
dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
}
std::string formatLiteral;
if (FormatConverter::toString(mFormat, formatLiteral)) {
dst->append(base::StringPrintf("%*s- format: %s\n", spaces, "", formatLiteral.c_str()));
}
if (!mSamplingRates.empty()) {
dst->append(base::StringPrintf("%*s- sampling rates:", spaces, ""));
for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
dst->append(base::StringPrintf("%d", *it));
dst->append(++it == mSamplingRates.end() ? "" : ", ");
}
dst->append("\n");
}
if (!mChannelMasks.empty()) {
dst->append(base::StringPrintf("%*s- channel masks:", spaces, ""));
for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
dst->append(base::StringPrintf("0x%04x", *it));
dst->append(++it == mChannelMasks.end() ? "" : ", ");
}
dst->append("\n");
}
}
ssize_t AudioProfileVectorBase::add(const sp<AudioProfile> &profile)
{
ssize_t index = size();
push_back(profile);
return index;
}
void AudioProfileVectorBase::clearProfiles()
{
for (auto it = begin(); it != end();) {
if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
it = erase(it);
} else {
(*it)->clear();
++it;
}
}
}
sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfile() const
{
for (const auto &profile : *this) {
if (profile->isValid()) {
return profile;
}
}
return nullptr;
}
sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfileFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->isValid() && profile->getFormat() == format) {
return profile;
}
}
return nullptr;
}
FormatVector AudioProfileVectorBase::getSupportedFormats() const
{
FormatVector supportedFormats;
for (const auto &profile : *this) {
if (profile->hasValidFormat()) {
supportedFormats.push_back(profile->getFormat());
}
}
return supportedFormats;
}
bool AudioProfileVectorBase::hasDynamicChannelsFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->getFormat() == format && profile->isDynamicChannels()) {
return true;
}
}
return false;
}
bool AudioProfileVectorBase::hasDynamicFormat() const
{
for (const auto &profile : *this) {
if (profile->isDynamicFormat()) {
return true;
}
}
return false;
}
bool AudioProfileVectorBase::hasDynamicProfile() const
{
for (const auto &profile : *this) {
if (profile->isDynamic()) {
return true;
}
}
return false;
}
bool AudioProfileVectorBase::hasDynamicRateFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->getFormat() == format && profile->isDynamicRate()) {
return true;
}
}
return false;
}
void AudioProfileVectorBase::dump(std::string *dst, int spaces) const
{
dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, ""));
for (size_t i = 0; i < size(); i++) {
dst->append(base::StringPrintf("%*sProfile %zu:", spaces + 4, "", i));
std::string profileStr;
at(i)->dump(&profileStr, spaces + 8);
dst->append(profileStr);
}
}
} // namespace android

@ -0,0 +1,130 @@
/*
* Copyright (C) 2019 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 <string>
#include <media/AudioGain.h>
#include <media/AudioProfile.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <system/audio.h>
#include <cutils/config_utils.h>
namespace android {
class AudioPortFoundation : public virtual RefBase
{
public:
AudioPortFoundation(const std::string& name, audio_port_type_t type, audio_port_role_t role) :
mName(name), mType(type), mRole(role) {}
virtual ~AudioPortFoundation() = default;
void setName(const std::string &name) { mName = name; }
const std::string &getName() const { return mName; }
audio_port_type_t getType() const { return mType; }
audio_port_role_t getRole() const { return mRole; }
virtual const std::string getTagName() const = 0;
void setGains(const AudioGains &gains) { mGains = gains; }
const AudioGains &getGains() const { return mGains; }
virtual void toAudioPort(struct audio_port *port) const;
virtual AudioProfileVectorBase* getAudioProfileVectorBase() const = 0;
virtual void addAudioProfile(const sp<AudioProfile> &profile) {
getAudioProfileVectorBase()->add(profile);
}
virtual void clearAudioProfiles() {
getAudioProfileVectorBase()->clearProfiles();
}
bool hasValidAudioProfile() const { return getAudioProfileVectorBase()->hasValidProfile(); }
status_t checkGain(const struct audio_gain_config *gainConfig, int index) const {
if (index < 0 || (size_t)index >= mGains.size()) {
return BAD_VALUE;
}
return mGains[index]->checkConfig(gainConfig);
}
bool useInputChannelMask() const
{
return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
}
void dump(std::string *dst, int spaces, bool verbose = true) const;
AudioGains mGains; // gain controllers
protected:
std::string mName;
audio_port_type_t mType;
audio_port_role_t mRole;
};
template <typename ProfileVector,
typename = typename std::enable_if<std::is_base_of<
AudioProfileVectorBase, ProfileVector>::value>::type>
class AudioPortBase : public AudioPortFoundation
{
public:
AudioPortBase(const std::string& name, audio_port_type_t type, audio_port_role_t role) :
AudioPortFoundation(name, type, role) {}
virtual ~AudioPortBase() {}
AudioProfileVectorBase* getAudioProfileVectorBase() const override {
return static_cast<AudioProfileVectorBase*>(const_cast<ProfileVector*>(&mProfiles));
}
void addAudioProfile(const sp<AudioProfile> &profile) override { mProfiles.add(profile); }
void clearAudioProfiles() override { return mProfiles.clearProfiles(); }
void setAudioProfiles(const ProfileVector &profiles) { mProfiles = profiles; }
ProfileVector &getAudioProfiles() { return mProfiles; }
protected:
ProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
};
class AudioPortConfigBase : public virtual RefBase
{
public:
virtual ~AudioPortConfigBase() = default;
virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
struct audio_port_config *backupConfig = NULL) = 0;
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const = 0;
unsigned int getSamplingRate() const { return mSamplingRate; }
audio_format_t getFormat() const { return mFormat; }
audio_channel_mask_t getChannelMask() const { return mChannelMask; }
protected:
unsigned int mSamplingRate = 0u;
audio_format_t mFormat = AUDIO_FORMAT_INVALID;
audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
struct audio_gain_config mGain = { .index = -1 };
};
} // namespace android

@ -16,19 +16,19 @@
#pragma once #pragma once
#include <string>
#include <vector>
#include <media/AudioContainers.h> #include <media/AudioContainers.h>
#include <system/audio.h> #include <system/audio.h>
#include <utils/RefBase.h> #include <utils/RefBase.h>
#include <utils/String8.h>
#include "policy.h"
namespace android { namespace android {
class AudioProfile : public virtual RefBase class AudioProfile final : public RefBase
{ {
public: public:
static sp<AudioProfile> createFullDynamic(); static sp<AudioProfile> createFullDynamic(audio_format_t dynamicFormat = AUDIO_FORMAT_DEFAULT);
AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate); AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
AudioProfile(audio_format_t format, AudioProfile(audio_format_t format,
@ -49,14 +49,6 @@ public:
} }
bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; } bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; }
status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const;
status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask,
audio_channel_mask_t &updatedChannelMask,
audio_port_type_t portType,
audio_port_role_t portRole) const;
status_t checkCompatibleSamplingRate(uint32_t samplingRate,
uint32_t &updatedSamplingRate) const;
bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; } bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
bool hasValidRates() const { return !mSamplingRates.empty(); } bool hasValidRates() const { return !mSamplingRates.empty(); }
bool hasValidChannels() const { return !mChannelMasks.empty(); } bool hasValidChannels() const { return !mChannelMasks.empty(); }
@ -72,11 +64,11 @@ public:
bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; } bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; }
void dump(String8 *dst, int spaces) const; void dump(std::string *dst, int spaces) const;
private: private:
String8 mName; std::string mName;
audio_format_t mFormat; audio_format_t mFormat; // The format for an audio profile should only be set when initialized.
ChannelMaskSet mChannelMasks; ChannelMaskSet mChannelMasks;
SampleRateSet mSamplingRates; SampleRateSet mSamplingRates;
@ -85,35 +77,16 @@ private:
bool mIsDynamicRate = false; bool mIsDynamicRate = false;
}; };
class AudioProfileVectorBase : public std::vector<sp<AudioProfile> >
class AudioProfileVector : public std::vector<sp<AudioProfile> >
{ {
public: public:
ssize_t add(const sp<AudioProfile> &profile); virtual ~AudioProfileVectorBase() = default;
// This API is intended to be used by the policy manager once retrieving capabilities
// for a profile with dynamic format, rate and channels attributes
ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd);
void appendProfiles(const AudioProfileVector& audioProfiles) {
insert(end(), audioProfiles.begin(), audioProfiles.end());
}
status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask, virtual ssize_t add(const sp<AudioProfile> &profile);
audio_format_t format) const;
status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask, // If the profile is dynamic format and has valid format, it will be removed when doing
audio_format_t &format, // clearProfiles(). Otherwise, AudioProfile::clear() will be called.
audio_port_type_t portType, virtual void clearProfiles();
audio_port_role_t portRole) const;
void clearProfiles();
// Assuming that this profile vector contains input profiles,
// find the best matching config from 'outputProfiles', according to
// the given preferences for audio formats and channel masks.
// Note: std::vectors are used because specialized containers for formats
// and channels can be sorted and use their own ordering.
status_t findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles,
const std::vector<audio_format_t>& preferredFormats, // order: most pref -> least pref
const std::vector<audio_channel_mask_t>& preferredOutputChannels,
bool preferHigherSamplingRates,
audio_config_base *bestOutputConfig) const;
sp<AudioProfile> getFirstValidProfile() const; sp<AudioProfile> getFirstValidProfile() const;
sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const; sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
@ -121,19 +94,11 @@ public:
FormatVector getSupportedFormats() const; FormatVector getSupportedFormats() const;
bool hasDynamicChannelsFor(audio_format_t format) const; bool hasDynamicChannelsFor(audio_format_t format) const;
bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; } bool hasDynamicFormat() const;
bool hasDynamicProfile() const; bool hasDynamicProfile() const;
bool hasDynamicRateFor(audio_format_t format) const; bool hasDynamicRateFor(audio_format_t format) const;
// One audio profile will be added for each format supported by Audio HAL virtual void dump(std::string *dst, int spaces) const;
void setFormats(const FormatVector &formats);
void dump(String8 *dst, int spaces) const;
private:
sp<AudioProfile> getProfileFor(audio_format_t format) const;
void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format);
void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format);
}; };
bool operator == (const AudioProfile &left, const AudioProfile &right); bool operator == (const AudioProfile &left, const AudioProfile &right);

@ -8,7 +8,7 @@ cc_library_static {
"src/AudioPatch.cpp", "src/AudioPatch.cpp",
"src/AudioPolicyMix.cpp", "src/AudioPolicyMix.cpp",
"src/AudioPort.cpp", "src/AudioPort.cpp",
"src/AudioProfile.cpp", "src/AudioProfileVector.cpp",
"src/AudioRoute.cpp", "src/AudioRoute.cpp",
"src/ClientDescriptor.cpp", "src/ClientDescriptor.cpp",
"src/DeviceDescriptor.cpp", "src/DeviceDescriptor.cpp",

@ -31,7 +31,7 @@ class AudioRoute;
class AudioPortVector : public Vector<sp<AudioPort> > class AudioPortVector : public Vector<sp<AudioPort> >
{ {
public: public:
sp<AudioPort> findByTagName(const String8 &tagName) const; sp<AudioPort> findByTagName(const std::string &tagName) const;
}; };

@ -29,6 +29,7 @@
#include <AudioPolicyMix.h> #include <AudioPolicyMix.h>
#include <EffectDescriptor.h> #include <EffectDescriptor.h>
#include <SoundTriggerSession.h> #include <SoundTriggerSession.h>
#include <media/AudioProfile.h>
namespace android { namespace android {
@ -118,9 +119,9 @@ public:
mSource = "AudioPolicyConfig::setDefault"; mSource = "AudioPolicyConfig::setDefault";
mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix; mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER); mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic()); mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC); sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic()); defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
sp<AudioProfile> micProfile = new AudioProfile( sp<AudioProfile> micProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000); AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
defaultInputDevice->addAudioProfile(micProfile); defaultInputDevice->addAudioProfile(micProfile);
@ -132,14 +133,14 @@ public:
mDefaultOutputDevice->attach(module); mDefaultOutputDevice->attach(module);
defaultInputDevice->attach(module); defaultInputDevice->attach(module);
sp<OutputProfile> outProfile = new OutputProfile(String8("primary")); sp<OutputProfile> outProfile = new OutputProfile("primary");
outProfile->addAudioProfile( outProfile->addAudioProfile(
new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100)); new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
outProfile->addSupportedDevice(mDefaultOutputDevice); outProfile->addSupportedDevice(mDefaultOutputDevice);
outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY); outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
module->addOutputProfile(outProfile); module->addOutputProfile(outProfile);
sp<InputProfile> inProfile = new InputProfile(String8("primary")); sp<InputProfile> inProfile = new InputProfile("primary");
inProfile->addAudioProfile(micProfile); inProfile->addAudioProfile(micProfile);
inProfile->addSupportedDevice(defaultInputDevice); inProfile->addSupportedDevice(defaultInputDevice);
module->addInputProfile(inProfile); module->addInputProfile(inProfile);

@ -17,9 +17,10 @@
#pragma once #pragma once
#include "AudioCollections.h" #include "AudioCollections.h"
#include "AudioProfile.h" #include "AudioProfileVector.h"
#include "HandleGenerator.h" #include "HandleGenerator.h"
#include <media/AudioGain.h> #include <media/AudioGain.h>
#include <media/AudioPortBase.h>
#include <utils/String8.h> #include <utils/String8.h>
#include <utils/Vector.h> #include <utils/Vector.h>
#include <utils/RefBase.h> #include <utils/RefBase.h>
@ -32,25 +33,15 @@ namespace android {
class HwModule; class HwModule;
class AudioRoute; class AudioRoute;
class AudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t> class AudioPort : public virtual RefBase, public AudioPortBase<AudioProfileVector>,
private HandleGenerator<audio_port_handle_t>
{ {
public: public:
AudioPort(const String8& name, audio_port_type_t type, audio_port_role_t role) : AudioPort(const std::string& name, audio_port_type_t type, audio_port_role_t role) :
mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {} AudioPortBase(name, type, role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
virtual ~AudioPort() {} virtual ~AudioPort() {}
void setName(const String8 &name) { mName = name; }
const String8 &getName() const { return mName; }
audio_port_type_t getType() const { return mType; }
audio_port_role_t getRole() const { return mRole; }
virtual const String8 getTagName() const = 0;
void setGains(const AudioGains &gains) { mGains = gains; }
const AudioGains &getGains() const { return mGains; }
virtual void setFlags(uint32_t flags) virtual void setFlags(uint32_t flags)
{ {
//force direct flag if offload flag is set: offloading implies a direct output stream //force direct flag if offload flag is set: offloading implies a direct output stream
@ -70,18 +61,9 @@ public:
// Audio port IDs are in a different namespace than AudioFlinger unique IDs // Audio port IDs are in a different namespace than AudioFlinger unique IDs
static audio_port_handle_t getNextUniqueId(); static audio_port_handle_t getNextUniqueId();
virtual void toAudioPort(struct audio_port *port) const;
virtual void importAudioPort(const sp<AudioPort>& port, bool force = false); virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
void addAudioProfile(const sp<AudioProfile> &profile) { mProfiles.add(profile); } bool hasDynamicAudioProfile() const { return getAudioProfileVectorBase()->hasDynamicProfile(); }
void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; }
AudioProfileVector &getAudioProfiles() { return mProfiles; }
bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); }
bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); }
// searches for an exact match // searches for an exact match
virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const; virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
@ -95,10 +77,6 @@ public:
return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole); return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole);
} }
void clearAudioProfiles() { return mProfiles.clearProfiles(); }
status_t checkGain(const struct audio_gain_config *gainConfig, int index) const;
void pickAudioProfile(uint32_t &samplingRate, void pickAudioProfile(uint32_t &samplingRate,
audio_channel_mask_t &channelMask, audio_channel_mask_t &channelMask,
audio_format_t &format) const; audio_format_t &format) const;
@ -121,12 +99,6 @@ public:
const char *getModuleName() const; const char *getModuleName() const;
sp<HwModule> getModule() const { return mModule; } sp<HwModule> getModule() const { return mModule; }
bool useInputChannelMask() const
{
return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
}
inline bool isDirectOutput() const inline bool isDirectOutput() const
{ {
return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
@ -136,44 +108,36 @@ public:
void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); } void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
const AudioRouteVector &getRoutes() const { return mRoutes; } const AudioRouteVector &getRoutes() const { return mRoutes; }
void dump(String8 *dst, int spaces, bool verbose = true) const;
void log(const char* indent) const; void log(const char* indent) const;
AudioGains mGains; // gain controllers
private: private:
void pickChannelMask(audio_channel_mask_t &channelMask, void pickChannelMask(audio_channel_mask_t &channelMask,
const ChannelMaskSet &channelMasks) const; const ChannelMaskSet &channelMasks) const;
void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const; void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;
sp<HwModule> mModule; // audio HW module exposing this I/O stream
String8 mName;
audio_port_type_t mType;
audio_port_role_t mRole;
uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...). uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).
AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels) sp<HwModule> mModule; // audio HW module exposing this I/O stream
AudioRouteVector mRoutes; // Routes involving this port AudioRouteVector mRoutes; // Routes involving this port
}; };
class AudioPortConfig : public virtual RefBase class AudioPortConfig : public AudioPortConfigBase
{ {
public: public:
status_t applyAudioPortConfig(const struct audio_port_config *config, status_t applyAudioPortConfig(const struct audio_port_config *config,
struct audio_port_config *backupConfig = NULL); struct audio_port_config *backupConfig = NULL) override;
virtual void toAudioPortConfig(struct audio_port_config *dstConfig, virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const = 0; const struct audio_port_config *srcConfig = NULL) const override;
virtual sp<AudioPort> getAudioPort() const = 0; virtual sp<AudioPort> getAudioPort() const = 0;
virtual bool hasSameHwModuleAs(const sp<AudioPortConfig>& other) const { virtual bool hasSameHwModuleAs(const sp<AudioPortConfig>& other) const {
return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) && return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) &&
(other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle()); (other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
} }
bool hasGainController(bool canUseForVolume = false) const; bool hasGainController(bool canUseForVolume = false) const;
unsigned int mSamplingRate = 0u;
audio_format_t mFormat = AUDIO_FORMAT_INVALID;
audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
struct audio_gain_config mGain = { .index = -1 };
union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE }; union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
}; };

@ -0,0 +1,68 @@
/*
* 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 <media/AudioProfile.h>
#include <system/audio.h>
namespace android {
class AudioProfileVector : public AudioProfileVectorBase {
public:
virtual ~AudioProfileVector() = default;
ssize_t add(const sp<AudioProfile> &profile) override;
// This API is intended to be used by the policy manager once retrieving capabilities
// for a profile with dynamic format, rate and channels attributes
ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd);
void appendProfiles(const AudioProfileVectorBase& audioProfiles) {
insert(end(), audioProfiles.begin(), audioProfiles.end());
}
status_t checkExactProfile(const uint32_t samplingRate,
audio_channel_mask_t channelMask,
audio_format_t format) const;
status_t checkCompatibleProfile(uint32_t &samplingRate,
audio_channel_mask_t &channelMask,
audio_format_t &format,
audio_port_type_t portType,
audio_port_role_t portRole) const;
// Assuming that this profile vector contains input profiles,
// find the best matching config from 'outputProfiles', according to
// the given preferences for audio formats and channel masks.
// Note: std::vectors are used because specialized containers for formats
// and channels can be sorted and use their own ordering.
status_t findBestMatchingOutputConfig(
const AudioProfileVector &outputProfiles,
const std::vector<audio_format_t> &preferredFormats, // order: most pref -> least pref
const std::vector<audio_channel_mask_t> &preferredOutputChannels,
bool preferHigherSamplingRates,
audio_config_base *bestOutputConfig) const;
// One audio profile will be added for each format supported by Audio HAL
void setFormats(const FormatVector &formats);
private:
sp<AudioProfile> getProfileFor(audio_format_t format) const;
void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format);
void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format);
};
} // namespace android

@ -30,13 +30,13 @@ class DeviceDescriptor : public AudioPort, public AudioPortConfig
{ {
public: public:
// Note that empty name refers by convention to a generic device. // Note that empty name refers by convention to a generic device.
explicit DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8("")); explicit DeviceDescriptor(audio_devices_t type, const std::string &tagName = "");
DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats, DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
const String8 &tagName = String8("")); const std::string &tagName = "");
virtual ~DeviceDescriptor() {} virtual ~DeviceDescriptor() {}
virtual const String8 getTagName() const { return mTagName; } virtual const std::string getTagName() const { return mTagName; }
audio_devices_t type() const { return mDeviceType; } audio_devices_t type() const { return mDeviceType; }
String8 address() const { return mAddress; } String8 address() const { return mAddress; }
@ -75,7 +75,7 @@ public:
private: private:
String8 mAddress{""}; String8 mAddress{""};
String8 mTagName; // Unique human readable identifier for a device port found in conf file. std::string mTagName; // Unique human readable identifier for a device port found in conf file.
audio_devices_t mDeviceType; audio_devices_t mDeviceType;
FormatVector mEncodedFormats; FormatVector mEncodedFormats;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE; audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
@ -112,10 +112,17 @@ public:
* equal to AUDIO_PORT_HANDLE_NONE, it also returns a nullptr. * equal to AUDIO_PORT_HANDLE_NONE, it also returns a nullptr.
*/ */
sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const; sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
sp<DeviceDescriptor> getDeviceFromTagName(const String8 &tagName) const; sp<DeviceDescriptor> getDeviceFromTagName(const std::string &tagName) const;
DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const; DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const; audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const;
DeviceVector getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const;
sp<DeviceDescriptor> getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const;
// If there are devices with the given type and the devices to add is not empty,
// remove all the devices with the given type and add all the devices to add.
void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd);
bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; } bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; }
/** /**

@ -82,17 +82,17 @@ public:
status_t addInputProfile(const sp<IOProfile> &profile); status_t addInputProfile(const sp<IOProfile> &profile);
status_t addProfile(const sp<IOProfile> &profile); status_t addProfile(const sp<IOProfile> &profile);
status_t addOutputProfile(const String8& name, const audio_config_t *config, status_t addOutputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address); audio_devices_t device, const String8& address);
status_t removeOutputProfile(const String8& name); status_t removeOutputProfile(const std::string& name);
status_t addInputProfile(const String8& name, const audio_config_t *config, status_t addInputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address); audio_devices_t device, const String8& address);
status_t removeInputProfile(const String8& name); status_t removeInputProfile(const std::string& name);
audio_module_handle_t getHandle() const { return mHandle; } audio_module_handle_t getHandle() const { return mHandle; }
void setHandle(audio_module_handle_t handle); void setHandle(audio_module_handle_t handle);
sp<AudioPort> findPortByTagName(const String8 &tagName) const sp<AudioPort> findPortByTagName(const std::string &tagName) const
{ {
return mPorts.findByTagName(tagName); return mPorts.findByTagName(tagName);
} }

@ -18,6 +18,7 @@
#include "AudioPort.h" #include "AudioPort.h"
#include "DeviceDescriptor.h" #include "DeviceDescriptor.h"
#include "policy.h"
#include <utils/String8.h> #include <utils/String8.h>
#include <system/audio.h> #include <system/audio.h>
@ -33,7 +34,7 @@ class HwModule;
class IOProfile : public AudioPort class IOProfile : public AudioPort
{ {
public: public:
IOProfile(const String8 &name, audio_port_role_t role) IOProfile(const std::string &name, audio_port_role_t role)
: AudioPort(name, AUDIO_PORT_TYPE_MIX, role), : AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
maxOpenCount(1), maxOpenCount(1),
curOpenCount(0), curOpenCount(0),
@ -41,7 +42,7 @@ public:
curActiveCount(0) {} curActiveCount(0) {}
// For a Profile aka MixPort, tag name and name are equivalent. // For a Profile aka MixPort, tag name and name are equivalent.
virtual const String8 getTagName() const { return getName(); } virtual const std::string getTagName() const { return getName(); }
// FIXME: this is needed because shared MMAP stream clients use the same audio session. // FIXME: this is needed because shared MMAP stream clients use the same audio session.
// Once capture clients are tracked individually and not per session this can be removed // Once capture clients are tracked individually and not per session this can be removed
@ -183,13 +184,13 @@ private:
class InputProfile : public IOProfile class InputProfile : public IOProfile
{ {
public: public:
explicit InputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {} explicit InputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
}; };
class OutputProfile : public IOProfile class OutputProfile : public IOProfile
{ {
public: public:
explicit OutputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {} explicit OutputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
}; };
} // namespace android } // namespace android

@ -24,7 +24,7 @@
namespace android { namespace android {
sp<AudioPort> AudioPortVector::findByTagName(const String8 &tagName) const sp<AudioPort> AudioPortVector::findByTagName(const std::string &tagName) const
{ {
for (const auto& port : *this) { for (const auto& port : *this) {
if (port->getTagName() == tagName) { if (port->getTagName() == tagName) {

@ -34,8 +34,8 @@ AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile,
{ {
if (profile != NULL) { if (profile != NULL) {
profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat); profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
if (profile->mGains.size() > 0) { if (profile->getGains().size() > 0) {
profile->mGains[0]->getDefaultConfig(&mGain); profile->getGains()[0]->getDefaultConfig(&mGain);
} }
} }
} }
@ -212,7 +212,7 @@ status_t AudioInputDescriptor::open(const audio_config_t *config,
mDevice = device; mDevice = device;
ALOGV("opening input for device %s profile %p name %s", ALOGV("opening input for device %s profile %p name %s",
mDevice->toString().c_str(), mProfile.get(), mProfile->getName().string()); mDevice->toString().c_str(), mProfile.get(), mProfile->getName().c_str());
audio_devices_t deviceType = mDevice->type(); audio_devices_t deviceType = mDevice->type();

@ -40,8 +40,8 @@ AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
{ {
if (mPort.get() != nullptr) { if (mPort.get() != nullptr) {
mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat); mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
if (mPort->mGains.size() > 0) { if (mPort->getGains().size() > 0) {
mPort->mGains[0]->getDefaultConfig(&mGain); mPort->getGains()[0]->getDefaultConfig(&mGain);
} }
} }
} }
@ -483,7 +483,7 @@ status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
mFlags = (audio_output_flags_t)(mFlags | flags); mFlags = (audio_output_flags_t)(mFlags | flags);
ALOGV("opening output for device %s profile %p name %s", ALOGV("opening output for device %s profile %p name %s",
mDevices.toString().c_str(), mProfile.get(), mProfile->getName().string()); mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(), status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
output, output,

@ -30,7 +30,7 @@ namespace android {
// --- AudioPort class implementation // --- AudioPort class implementation
void AudioPort::attach(const sp<HwModule>& module) void AudioPort::attach(const sp<HwModule>& module)
{ {
ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.string()); ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.c_str());
mModule = module; mModule = module;
} }
@ -60,49 +60,6 @@ const char *AudioPort::getModuleName() const
return mModule != 0 ? mModule->getName() : "invalid module"; return mModule != 0 ? mModule->getName() : "invalid module";
} }
void AudioPort::toAudioPort(struct audio_port *port) const
{
// TODO: update this function once audio_port structure reflects the new profile definition.
// For compatibility reason: flatening the AudioProfile into audio_port structure.
FormatSet flatenedFormats;
SampleRateSet flatenedRates;
ChannelMaskSet flatenedChannels;
for (const auto& profile : mProfiles) {
if (profile->isValid()) {
audio_format_t formatToExport = profile->getFormat();
const SampleRateSet &ratesToExport = profile->getSampleRates();
const ChannelMaskSet &channelsToExport = profile->getChannels();
flatenedFormats.insert(formatToExport);
flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());
if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__);
return;
}
}
}
port->role = mRole;
port->type = mType;
strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
port->num_sample_rates = flatenedRates.size();
port->num_channel_masks = flatenedChannels.size();
port->num_formats = flatenedFormats.size();
std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);
ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS);
for (size_t i = 0; i < port->num_gains; i++) {
port->gains[i] = mGains[i]->getGain();
}
}
void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused) void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
{ {
for (const auto& profileToImport : port->mProfiles) { for (const auto& profileToImport : port->mProfiles) {
@ -324,40 +281,13 @@ void AudioPort::pickAudioProfile(uint32_t &samplingRate,
} }
} }
} }
ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(), ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.c_str(),
samplingRate, channelMask, format); samplingRate, channelMask, format);
} }
status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
{
if (index < 0 || (size_t)index >= mGains.size()) {
return BAD_VALUE;
}
return mGains[index]->checkConfig(gainConfig);
}
void AudioPort::dump(String8 *dst, int spaces, bool verbose) const
{
if (!mName.isEmpty()) {
dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
}
if (verbose) {
mProfiles.dump(dst, spaces);
if (mGains.size() != 0) {
dst->appendFormat("%*s- gains:\n", spaces, "");
for (size_t i = 0; i < mGains.size(); i++) {
std::string gainStr;
mGains[i]->dump(&gainStr, spaces + 2, i);
dst->append(gainStr.c_str());
}
}
}
}
void AudioPort::log(const char* indent) const void AudioPort::log(const char* indent) const
{ {
ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole); ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
} }
// --- AudioPortConfig class implementation // --- AudioPortConfig class implementation

@ -26,95 +26,31 @@
#include <utils/Errors.h> #include <utils/Errors.h>
#include "AudioPort.h" #include "AudioPort.h"
#include "AudioProfile.h" #include "AudioProfileVector.h"
#include "HwModule.h" #include "HwModule.h"
#include "TypeConverter.h" #include "policy.h"
namespace android { namespace android {
bool operator == (const AudioProfile &left, const AudioProfile &compareTo) status_t checkExact(const sp<AudioProfile> &audioProfile, uint32_t samplingRate,
audio_channel_mask_t channelMask, audio_format_t format)
{ {
return (left.getFormat() == compareTo.getFormat()) && if (audio_formats_match(format, audioProfile->getFormat()) &&
(left.getChannels() == compareTo.getChannels()) && audioProfile->supportsChannels(channelMask) &&
(left.getSampleRates() == compareTo.getSampleRates()); audioProfile->supportsRate(samplingRate)) {
}
static AudioProfile* createFullDynamicImpl()
{
AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat,
ChannelMaskSet(), SampleRateSet());
dynamicProfile->setDynamicFormat(true);
dynamicProfile->setDynamicChannels(true);
dynamicProfile->setDynamicRate(true);
return dynamicProfile;
}
// static
sp<AudioProfile> AudioProfile::createFullDynamic()
{
static sp<AudioProfile> dynamicProfile = createFullDynamicImpl();
return dynamicProfile;
}
AudioProfile::AudioProfile(audio_format_t format,
audio_channel_mask_t channelMasks,
uint32_t samplingRate) :
mName(String8("")),
mFormat(format)
{
mChannelMasks.insert(channelMasks);
mSamplingRates.insert(samplingRate);
}
AudioProfile::AudioProfile(audio_format_t format,
const ChannelMaskSet &channelMasks,
const SampleRateSet &samplingRateCollection) :
mName(String8("")),
mFormat(format),
mChannelMasks(channelMasks),
mSamplingRates(samplingRateCollection) {}
void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
{
if (mIsDynamicChannels) {
mChannelMasks = channelMasks;
}
}
void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
{
if (mIsDynamicRate) {
mSamplingRates = sampleRates;
}
}
void AudioProfile::clear()
{
if (mIsDynamicChannels) {
mChannelMasks.clear();
}
if (mIsDynamicRate) {
mSamplingRates.clear();
}
}
status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask,
audio_format_t format) const
{
if (audio_formats_match(format, mFormat) &&
supportsChannels(channelMask) &&
supportsRate(samplingRate)) {
return NO_ERROR; return NO_ERROR;
} }
return BAD_VALUE; return BAD_VALUE;
} }
status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, status_t checkCompatibleSamplingRate(const sp<AudioProfile> &audioProfile,
uint32_t &updatedSamplingRate) const uint32_t samplingRate,
uint32_t &updatedSamplingRate)
{ {
ALOG_ASSERT(samplingRate > 0); ALOG_ASSERT(samplingRate > 0);
if (mSamplingRates.empty()) { const SampleRateSet sampleRates = audioProfile->getSampleRates();
if (sampleRates.empty()) {
updatedSamplingRate = samplingRate; updatedSamplingRate = samplingRate;
return NO_ERROR; return NO_ERROR;
} }
@ -122,17 +58,17 @@ status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate,
// Search for the closest supported sampling rate that is above (preferred) // Search for the closest supported sampling rate that is above (preferred)
// or below (acceptable) the desired sampling rate, within a permitted ratio. // or below (acceptable) the desired sampling rate, within a permitted ratio.
// The sampling rates are sorted in ascending order. // The sampling rates are sorted in ascending order.
auto desiredRate = mSamplingRates.lower_bound(samplingRate); auto desiredRate = sampleRates.lower_bound(samplingRate);
// Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
if (desiredRate != mSamplingRates.end()) { if (desiredRate != sampleRates.end()) {
if (*desiredRate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { if (*desiredRate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
updatedSamplingRate = *desiredRate; updatedSamplingRate = *desiredRate;
return NO_ERROR; return NO_ERROR;
} }
} }
// But if we have to up-sample from a lower sampling rate, that's OK. // But if we have to up-sample from a lower sampling rate, that's OK.
if (desiredRate != mSamplingRates.begin()) { if (desiredRate != sampleRates.begin()) {
uint32_t candidate = *(--desiredRate); uint32_t candidate = *(--desiredRate);
if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
updatedSamplingRate = candidate; updatedSamplingRate = candidate;
@ -143,12 +79,14 @@ status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate,
return BAD_VALUE; return BAD_VALUE;
} }
status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask, status_t checkCompatibleChannelMask(const sp<AudioProfile> &audioProfile,
audio_channel_mask_t &updatedChannelMask, audio_channel_mask_t channelMask,
audio_port_type_t portType, audio_channel_mask_t &updatedChannelMask,
audio_port_role_t portRole) const audio_port_type_t portType,
audio_port_role_t portRole)
{ {
if (mChannelMasks.empty()) { const ChannelMaskSet channelMasks = audioProfile->getChannels();
if (channelMasks.empty()) {
updatedChannelMask = channelMask; updatedChannelMask = channelMask;
return NO_ERROR; return NO_ERROR;
} }
@ -157,7 +95,7 @@ status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMa
== AUDIO_CHANNEL_REPRESENTATION_INDEX; == AUDIO_CHANNEL_REPRESENTATION_INDEX;
const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
int bestMatch = 0; int bestMatch = 0;
for (const auto &supported : mChannelMasks) { for (const auto &supported : channelMasks) {
if (supported == channelMask) { if (supported == channelMask) {
// Exact matches always taken. // Exact matches always taken.
updatedChannelMask = channelMask; updatedChannelMask = channelMask;
@ -235,37 +173,6 @@ status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMa
return bestMatch > 0 ? NO_ERROR : BAD_VALUE; return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
} }
void AudioProfile::dump(String8 *dst, int spaces) const
{
dst->appendFormat("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
mIsDynamicChannels ? "[dynamic channels]" : "",
mIsDynamicRate ? "[dynamic rates]" : "");
if (mName.length() != 0) {
dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
}
std::string formatLiteral;
if (FormatConverter::toString(mFormat, formatLiteral)) {
dst->appendFormat("%*s- format: %s\n", spaces, "", formatLiteral.c_str());
}
if (!mSamplingRates.empty()) {
dst->appendFormat("%*s- sampling rates:", spaces, "");
for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
dst->appendFormat("%d", *it);
dst->append(++it == mSamplingRates.end() ? "" : ", ");
}
dst->append("\n");
}
if (!mChannelMasks.empty()) {
dst->appendFormat("%*s- channel masks:", spaces, "");
for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
dst->appendFormat("0x%04x", *it);
dst->append(++it == mChannelMasks.end() ? "" : ", ");
}
dst->append("\n");
}
}
ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile) ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
{ {
ssize_t index = size(); ssize_t index = size();
@ -311,7 +218,7 @@ ssize_t AudioProfileVector::addProfileFromHal(const sp<AudioProfile> &profileToA
return add(profileToAdd); return add(profileToAdd);
} }
status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, status_t AudioProfileVector::checkExactProfile(const uint32_t samplingRate,
audio_channel_mask_t channelMask, audio_channel_mask_t channelMask,
audio_format_t format) const audio_format_t format) const
{ {
@ -320,7 +227,7 @@ status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate,
} }
for (const auto& profile : *this) { for (const auto& profile : *this) {
if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) { if (checkExact(profile, samplingRate, channelMask, format) == NO_ERROR) {
return NO_ERROR; return NO_ERROR;
} }
} }
@ -353,9 +260,9 @@ status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate,
// rate and channels as well // rate and channels as well
audio_channel_mask_t updatedChannels; audio_channel_mask_t updatedChannels;
uint32_t updatedRate; uint32_t updatedRate;
if (profile->checkCompatibleChannelMask(channelMask, updatedChannels, if (checkCompatibleChannelMask(profile, channelMask, updatedChannels,
portType, portRole) == NO_ERROR && portType, portRole) == NO_ERROR &&
profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) { checkCompatibleSamplingRate(profile, samplingRate, updatedRate) == NO_ERROR) {
// for inexact checks we take the first linear pcm format due to sorting. // for inexact checks we take the first linear pcm format due to sorting.
format = formatToCompare; format = formatToCompare;
channelMask = updatedChannels; channelMask = updatedChannels;
@ -367,18 +274,6 @@ status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate,
return BAD_VALUE; return BAD_VALUE;
} }
void AudioProfileVector::clearProfiles()
{
for (auto it = begin(); it != end();) {
if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
it = erase(it);
} else {
(*it)->clear();
++it;
}
}
}
// Returns an intersection between two possibly unsorted vectors and the contents of 'order'. // Returns an intersection between two possibly unsorted vectors and the contents of 'order'.
// The result is ordered according to 'order'. // The result is ordered according to 'order'.
template<typename T, typename Order> template<typename T, typename Order>
@ -449,67 +344,6 @@ status_t AudioProfileVector::findBestMatchingOutputConfig(const AudioProfileVect
return BAD_VALUE; return BAD_VALUE;
} }
sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
{
for (const auto &profile : *this) {
if (profile->isValid()) {
return profile;
}
}
return nullptr;
}
sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->isValid() && profile->getFormat() == format) {
return profile;
}
}
return nullptr;
}
FormatVector AudioProfileVector::getSupportedFormats() const
{
FormatVector supportedFormats;
for (const auto &profile : *this) {
if (profile->hasValidFormat()) {
supportedFormats.push_back(profile->getFormat());
}
}
return supportedFormats;
}
bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->getFormat() == format && profile->isDynamicChannels()) {
return true;
}
}
return false;
}
bool AudioProfileVector::hasDynamicProfile() const
{
for (const auto &profile : *this) {
if (profile->isDynamic()) {
return true;
}
}
return false;
}
bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->getFormat() == format && profile->isDynamicRate()) {
return true;
}
}
return false;
}
void AudioProfileVector::setFormats(const FormatVector &formats) void AudioProfileVector::setFormats(const FormatVector &formats)
{ {
// Only allow to change the format of dynamic profile // Only allow to change the format of dynamic profile
@ -528,15 +362,6 @@ void AudioProfileVector::setFormats(const FormatVector &formats)
} }
} }
void AudioProfileVector::dump(String8 *dst, int spaces) const
{
dst->appendFormat("%*s- Profiles:\n", spaces, "");
for (size_t i = 0; i < size(); i++) {
dst->appendFormat("%*sProfile %zu:", spaces + 4, "", i);
at(i)->dump(dst, spaces + 8);
}
}
sp<AudioProfile> AudioProfileVector::getProfileFor(audio_format_t format) const sp<AudioProfile> AudioProfileVector::getProfileFor(audio_format_t format) const
{ {
for (const auto &profile : *this) { for (const auto &profile : *this) {

@ -26,11 +26,11 @@ namespace android
void AudioRoute::dump(String8 *dst, int spaces) const void AudioRoute::dump(String8 *dst, int spaces) const
{ {
dst->appendFormat("%*s- Type: %s\n", spaces, "", mType == AUDIO_ROUTE_MUX ? "Mux" : "Mix"); dst->appendFormat("%*s- Type: %s\n", spaces, "", mType == AUDIO_ROUTE_MUX ? "Mux" : "Mix");
dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().string()); dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().c_str());
if (mSources.size() != 0) { if (mSources.size() != 0) {
dst->appendFormat("%*s- Sources: \n", spaces, ""); dst->appendFormat("%*s- Sources: \n", spaces, "");
for (size_t i = 0; i < mSources.size(); i++) { for (size_t i = 0; i < mSources.size(); i++) {
dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().string()); dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().c_str());
} }
} }
dst->append("\n"); dst->append("\n");
@ -41,10 +41,10 @@ bool AudioRoute::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort>
if (mSink == 0 || dstPort == 0 || dstPort != mSink) { if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
return false; return false;
} }
ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().string()); ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().c_str());
for (const auto &sourcePort : mSources) { for (const auto &sourcePort : mSources) {
if (sourcePort == srcPort) { if (sourcePort == srcPort) {
ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().string()); ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().c_str());
return true; return true;
} }
} }

@ -26,14 +26,14 @@
namespace android { namespace android {
DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) : DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const std::string &tagName) :
DeviceDescriptor(type, FormatVector{}, tagName) DeviceDescriptor(type, FormatVector{}, tagName)
{ {
} }
DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats, DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
const String8 &tagName) : const std::string &tagName) :
AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE, AudioPort("", AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE), AUDIO_PORT_ROLE_SOURCE),
mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats) mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
@ -255,7 +255,6 @@ DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const
audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN; audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
if ((isOutput == curIsOutput) && ((type & curType) != 0)) { if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
devices.add(itemAt(i)); devices.add(itemAt(i));
type &= ~curType;
ALOGV("DeviceVector::%s() for type %08x found %p", ALOGV("DeviceVector::%s() for type %08x found %p",
__func__, itemAt(i)->type(), itemAt(i).get()); __func__, itemAt(i)->type(), itemAt(i).get());
} }
@ -263,7 +262,7 @@ DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const
return devices; return devices;
} }
sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName) const sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const std::string &tagName) const
{ {
for (const auto& device : *this) { for (const auto& device : *this) {
if (device->getTagName() == tagName) { if (device->getTagName() == tagName) {
@ -273,6 +272,38 @@ sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName)
return nullptr; return nullptr;
} }
DeviceVector DeviceVector::getFirstDevicesFromTypes(
std::vector<audio_devices_t> orderedTypes) const
{
DeviceVector devices;
for (auto deviceType : orderedTypes) {
if (!(devices = getDevicesFromTypeMask(deviceType)).isEmpty()) {
break;
}
}
return devices;
}
sp<DeviceDescriptor> DeviceVector::getFirstExistingDevice(
std::vector<audio_devices_t> orderedTypes) const {
sp<DeviceDescriptor> device;
for (auto deviceType : orderedTypes) {
if ((device = getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT)) != nullptr) {
break;
}
}
return device;
}
void DeviceVector::replaceDevicesByType(
audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
DeviceVector devicesToRemove = getDevicesFromTypeMask(typeToRemove);
if (!devicesToRemove.isEmpty() && !devicesToAdd.isEmpty()) {
remove(devicesToRemove);
add(devicesToAdd);
}
}
void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const
{ {
if (isEmpty()) { if (isEmpty()) {
@ -343,8 +374,8 @@ void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) c
if (mId != 0) { if (mId != 0) {
dst->appendFormat("%*s- id: %2d\n", spaces, "", mId); dst->appendFormat("%*s- id: %2d\n", spaces, "", mId);
} }
if (!mTagName.isEmpty()) { if (!mTagName.empty()) {
dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.string()); dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.c_str());
} }
dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str()); dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str());
@ -352,7 +383,9 @@ void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) c
if (mAddress.size() != 0) { if (mAddress.size() != 0) {
dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string()); dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string());
} }
AudioPort::dump(dst, spaces, verbose); std::string portStr;
AudioPort::dump(&portStr, spaces, verbose);
dst->append(portStr.c_str());
} }
std::string DeviceDescriptor::toString() const std::string DeviceDescriptor::toString() const

@ -41,7 +41,7 @@ HwModule::~HwModule()
} }
} }
status_t HwModule::addOutputProfile(const String8& name, const audio_config_t *config, status_t HwModule::addOutputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address) audio_devices_t device, const String8& address)
{ {
sp<IOProfile> profile = new OutputProfile(name); sp<IOProfile> profile = new OutputProfile(name);
@ -95,7 +95,7 @@ void HwModule::setProfiles(const IOProfileCollection &profiles)
} }
} }
status_t HwModule::removeOutputProfile(const String8& name) status_t HwModule::removeOutputProfile(const std::string& name)
{ {
for (size_t i = 0; i < mOutputProfiles.size(); i++) { for (size_t i = 0; i < mOutputProfiles.size(); i++) {
if (mOutputProfiles[i]->getName() == name) { if (mOutputProfiles[i]->getName() == name) {
@ -110,7 +110,7 @@ status_t HwModule::removeOutputProfile(const String8& name)
return NO_ERROR; return NO_ERROR;
} }
status_t HwModule::addInputProfile(const String8& name, const audio_config_t *config, status_t HwModule::addInputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address) audio_devices_t device, const String8& address)
{ {
sp<IOProfile> profile = new InputProfile(name); sp<IOProfile> profile = new InputProfile(name);
@ -125,12 +125,12 @@ status_t HwModule::addInputProfile(const String8& name, const audio_config_t *co
profile->addSupportedDevice(devDesc); profile->addSupportedDevice(devDesc);
ALOGV("addInputProfile() name %s rate %d mask 0x%08x", ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
name.string(), config->sample_rate, config->channel_mask); name.c_str(), config->sample_rate, config->channel_mask);
return addInputProfile(profile); return addInputProfile(profile);
} }
status_t HwModule::removeInputProfile(const String8& name) status_t HwModule::removeInputProfile(const std::string& name)
{ {
for (size_t i = 0; i < mInputProfiles.size(); i++) { for (size_t i = 0; i < mInputProfiles.size(); i++) {
if (mInputProfiles[i]->getName() == name) { if (mInputProfiles[i]->getName() == name) {
@ -193,13 +193,13 @@ void HwModule::refreshSupportedDevices()
} }
DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route); DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route);
if (sourceDevicesForRoute.isEmpty()) { if (sourceDevicesForRoute.isEmpty()) {
ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string()); ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
continue; continue;
} }
sourceDevices.add(sourceDevicesForRoute); sourceDevices.add(sourceDevicesForRoute);
} }
if (sourceDevices.isEmpty()) { if (sourceDevices.isEmpty()) {
ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string()); ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
continue; continue;
} }
stream->setSupportedDevices(sourceDevices); stream->setSupportedDevices(sourceDevices);
@ -214,7 +214,7 @@ void HwModule::refreshSupportedDevices()
} }
sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(route); sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(route);
if (sinkDevice == 0) { if (sinkDevice == 0) {
ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().string()); ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().c_str());
continue; continue;
} }
sinkDevices.add(sinkDevice); sinkDevices.add(sinkDevice);
@ -335,7 +335,7 @@ sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices
if (allowToCreate) { if (allowToCreate) {
moduleDevice->attach(hwModule); moduleDevice->attach(hwModule);
moduleDevice->setAddress(devAddress); moduleDevice->setAddress(devAddress);
moduleDevice->setName(String8(name)); moduleDevice->setName(name);
} }
return moduleDevice; return moduleDevice;
} }
@ -359,8 +359,8 @@ sp<DeviceDescriptor> HwModuleCollection::createDevice(const audio_devices_t type
address); address);
return nullptr; return nullptr;
} }
sp<DeviceDescriptor> device = new DeviceDescriptor(type, String8(name)); sp<DeviceDescriptor> device = new DeviceDescriptor(type, name);
device->setName(String8(name)); device->setName(name);
device->setAddress(String8(address)); device->setAddress(String8(address));
device->setEncodedFormat(encodedFormat); device->setEncodedFormat(encodedFormat);

@ -107,7 +107,9 @@ bool IOProfile::isCompatibleProfile(const DeviceVector &devices,
void IOProfile::dump(String8 *dst) const void IOProfile::dump(String8 *dst) const
{ {
AudioPort::dump(dst, 4); std::string portStr;
AudioPort::dump(&portStr, 4);
dst->append(portStr.c_str());
dst->appendFormat(" - flags: 0x%04x", getFlags()); dst->appendFormat(" - flags: 0x%04x", getFlags());
std::string flagsLiteral; std::string flagsLiteral;

@ -430,7 +430,7 @@ Return<MixPortTraits::Element> MixPortTraits::deserialize(const xmlNode *child,
audio_port_role_t portRole = (role == Attributes::roleSource) ? audio_port_role_t portRole = (role == Attributes::roleSource) ?
AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK; AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
Element mixPort = new IOProfile(String8(name.c_str()), portRole); Element mixPort = new IOProfile(name, portRole);
AudioProfileTraits::Collection profiles; AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL); status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
@ -438,7 +438,7 @@ Return<MixPortTraits::Element> MixPortTraits::deserialize(const xmlNode *child,
return Status::fromStatusT(status); return Status::fromStatusT(status);
} }
if (profiles.empty()) { if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic()); profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
} }
mixPort->setAudioProfiles(profiles); mixPort->setAudioProfiles(profiles);
@ -508,7 +508,7 @@ Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *c
if (!encodedFormatsLiteral.empty()) { if (!encodedFormatsLiteral.empty()) {
encodedFormats = formatsFromString(encodedFormatsLiteral, " "); encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
} }
Element deviceDesc = new DeviceDescriptor(type, encodedFormats, String8(name.c_str())); Element deviceDesc = new DeviceDescriptor(type, encodedFormats, name);
std::string address = getXmlAttribute(cur, Attributes::address); std::string address = getXmlAttribute(cur, Attributes::address);
if (!address.empty()) { if (!address.empty()) {
@ -522,7 +522,7 @@ Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *c
return Status::fromStatusT(status); return Status::fromStatusT(status);
} }
if (profiles.empty()) { if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic()); profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
} }
deviceDesc->setAudioProfiles(profiles); deviceDesc->setAudioProfiles(profiles);
@ -532,7 +532,7 @@ Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *c
return Status::fromStatusT(status); return Status::fromStatusT(status);
} }
ALOGV("%s: adding device tag %s type %08x address %s", __func__, ALOGV("%s: adding device tag %s type %08x address %s", __func__,
deviceDesc->getName().string(), type, deviceDesc->address().string()); deviceDesc->getName().c_str(), type, deviceDesc->address().string());
return deviceDesc; return deviceDesc;
} }
@ -555,7 +555,7 @@ Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSer
return Status::fromStatusT(BAD_VALUE); return Status::fromStatusT(BAD_VALUE);
} }
// Convert Sink name to port pointer // Convert Sink name to port pointer
sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str())); sp<AudioPort> sink = ctx->findPortByTagName(sinkAttr);
if (sink == NULL) { if (sink == NULL) {
ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str()); ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
return Status::fromStatusT(BAD_VALUE); return Status::fromStatusT(BAD_VALUE);
@ -574,7 +574,7 @@ Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSer
char *devTag = strtok(sourcesLiteral.get(), ","); char *devTag = strtok(sourcesLiteral.get(), ",");
while (devTag != NULL) { while (devTag != NULL) {
if (strlen(devTag) != 0) { if (strlen(devTag) != 0) {
sp<AudioPort> source = ctx->findPortByTagName(String8(devTag)); sp<AudioPort> source = ctx->findPortByTagName(devTag);
if (source == NULL) { if (source == NULL) {
ALOGE("%s: no source found with name=%s", __func__, devTag); ALOGE("%s: no source found with name=%s", __func__, devTag);
return Status::fromStatusT(BAD_VALUE); return Status::fromStatusT(BAD_VALUE);
@ -648,7 +648,7 @@ Return<ModuleTraits::Element> ModuleTraits::deserialize(const xmlNode *cur, PtrS
ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag, ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag,
reinterpret_cast<const char*>(attachedDevice.get())); reinterpret_cast<const char*>(attachedDevice.get()));
sp<DeviceDescriptor> device = module->getDeclaredDevices(). sp<DeviceDescriptor> device = module->getDeclaredDevices().
getDeviceFromTagName(String8(reinterpret_cast<const char*>( getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
attachedDevice.get()))); attachedDevice.get())));
ctx->addAvailableDevice(device); ctx->addAvailableDevice(device);
} }
@ -663,7 +663,7 @@ Return<ModuleTraits::Element> ModuleTraits::deserialize(const xmlNode *cur, PtrS
ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag, ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag,
reinterpret_cast<const char*>(defaultOutputDevice.get())); reinterpret_cast<const char*>(defaultOutputDevice.get()));
sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName( sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(
String8(reinterpret_cast<const char*>(defaultOutputDevice.get()))); std::string(reinterpret_cast<const char*>(defaultOutputDevice.get())));
if (device != 0 && ctx->getDefaultOutputDevice() == 0) { if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
ctx->setDefaultOutputDevice(device); ctx->setDefaultOutputDevice(device);
ALOGV("%s: default is %08x", ALOGV("%s: default is %08x",

@ -136,27 +136,23 @@ status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced
return EngineBase::setForceUse(usage, config); return EngineBase::setForceUse(usage, config);
} }
audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy, DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
DeviceVector availableOutputDevices, DeviceVector availableOutputDevices,
DeviceVector availableInputDevices, DeviceVector availableInputDevices,
const SwAudioOutputCollection &outputs, const SwAudioOutputCollection &outputs) const
uint32_t outputDeviceTypesToIgnore) const
{ {
uint32_t device = AUDIO_DEVICE_NONE; DeviceVector devices;
uint32_t availableOutputDevicesType =
availableOutputDevices.types() & ~outputDeviceTypesToIgnore;
switch (strategy) { switch (strategy) {
case STRATEGY_TRANSMITTED_THROUGH_SPEAKER: case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
break; break;
case STRATEGY_SONIFICATION_RESPECTFUL: case STRATEGY_SONIFICATION_RESPECTFUL:
if (isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) { if (isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
device = getDeviceForStrategyInt( devices = getDevicesForStrategyInt(
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs, STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
outputDeviceTypesToIgnore);
} else { } else {
bool media_active_locally = bool media_active_locally =
outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC), outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC),
@ -165,17 +161,18 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
toVolumeSource(AUDIO_STREAM_ACCESSIBILITY), toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY); SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
// routing is same as media without the "remote" device // routing is same as media without the "remote" device
device = getDeviceForStrategyInt(STRATEGY_MEDIA, availableOutputDevices.remove(availableOutputDevices.getDevicesFromTypeMask(
AUDIO_DEVICE_OUT_REMOTE_SUBMIX));
devices = getDevicesForStrategyInt(STRATEGY_MEDIA,
availableOutputDevices, availableOutputDevices,
availableInputDevices, outputs, availableInputDevices, outputs);
AUDIO_DEVICE_OUT_REMOTE_SUBMIX | outputDeviceTypesToIgnore);
// if no media is playing on the device, check for mandatory use of "safe" speaker // if no media is playing on the device, check for mandatory use of "safe" speaker
// when media would have played on speaker, and the safe speaker path is available // when media would have played on speaker, and the safe speaker path is available
if (!media_active_locally if (!media_active_locally) {
&& (device & AUDIO_DEVICE_OUT_SPEAKER) devices.replaceDevicesByType(
&& (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { AUDIO_DEVICE_OUT_SPEAKER,
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; availableOutputDevices.getDevicesFromTypeMask(
device &= ~AUDIO_DEVICE_OUT_SPEAKER; AUDIO_DEVICE_OUT_SPEAKER_SAFE));
} }
} }
break; break;
@ -183,9 +180,8 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
case STRATEGY_DTMF: case STRATEGY_DTMF:
if (!isInCall()) { if (!isInCall()) {
// when off call, DTMF strategy follows the same rules as MEDIA strategy // when off call, DTMF strategy follows the same rules as MEDIA strategy
device = getDeviceForStrategyInt( devices = getDevicesForStrategyInt(
STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs, STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
outputDeviceTypesToIgnore);
break; break;
} }
// when in call, DTMF and PHONE strategies follow the same rules // when in call, DTMF and PHONE strategies follow the same rules
@ -197,24 +193,27 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
// - cannot route from voice call RX OR // - cannot route from voice call RX OR
// - audio HAL version is < 3.0 and TX device is on the primary HW module // - audio HAL version is < 3.0 and TX device is on the primary HW module
if (getPhoneState() == AUDIO_MODE_IN_CALL) { if (getPhoneState() == AUDIO_MODE_IN_CALL) {
audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION); audio_devices_t txDevice = getDeviceForInputSource(
AUDIO_SOURCE_VOICE_COMMUNICATION)->type();
sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput(); sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
audio_devices_t availPrimaryInputDevices = DeviceVector availPrimaryInputDevices =
availableInputDevices.getDeviceTypesFromHwModule(primaryOutput->getModuleHandle()); availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
// TODO: getPrimaryOutput return only devices from first module in // TODO: getPrimaryOutput return only devices from first module in
// audio_policy_configuration.xml, hearing aid is not there, but it's // audio_policy_configuration.xml, hearing aid is not there, but it's
// a primary device // a primary device
// FIXME: this is not the right way of solving this problem // FIXME: this is not the right way of solving this problem
audio_devices_t availPrimaryOutputDevices = DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypeMask(
(primaryOutput->supportedDevices().types() | AUDIO_DEVICE_OUT_HEARING_AID) & primaryOutput->supportedDevices().types());
availableOutputDevices.types(); availPrimaryOutputDevices.add(
availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID));
if (((availableInputDevices.types() &
AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) || if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
(((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) && String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
(primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) { ((availPrimaryInputDevices.getDevice(
availableOutputDevicesType = availPrimaryOutputDevices; txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
(primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) {
availableOutputDevices = availPrimaryOutputDevices;
} }
} }
// for phone strategy, we first consider the forced use and then the available devices by // for phone strategy, we first consider the forced use and then the available devices by
@ -222,49 +221,40 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) { switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
case AUDIO_POLICY_FORCE_BT_SCO: case AUDIO_POLICY_FORCE_BT_SCO:
if (!isInCall() || strategy != STRATEGY_DTMF) { if (!isInCall() || strategy != STRATEGY_DTMF) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; devices = availableOutputDevices.getDevicesFromTypeMask(
if (device) break; AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
if (!devices.isEmpty()) break;
} }
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; devices = availableOutputDevices.getFirstDevicesFromTypes({
if (device) break; AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; if (!devices.isEmpty()) break;
if (device) break;
// if SCO device is requested but no SCO device is available, fall back to default case // if SCO device is requested but no SCO device is available, fall back to default case
FALLTHROUGH_INTENDED; FALLTHROUGH_INTENDED;
default: // FORCE_NONE default: // FORCE_NONE
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID; devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
if (device) break; if (!devices.isEmpty()) break;
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
if (!isInCall() && if (!isInCall() &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) && (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
outputs.isA2dpSupported()) { outputs.isA2dpSupported()) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; devices = availableOutputDevices.getFirstDevicesFromTypes({
if (device) break; AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
if (device) break; if (!devices.isEmpty()) break;
} }
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; devices = availableOutputDevices.getFirstDevicesFromTypes({
if (device) break; AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET; AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
if (device) break; AUDIO_DEVICE_OUT_USB_DEVICE});
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE; if (!devices.isEmpty()) break;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
if (!isInCall()) { if (!isInCall()) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; devices = availableOutputDevices.getFirstDevicesFromTypes({
if (device) break; AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
if (device) break; if (!devices.isEmpty()) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
} }
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE; devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_EARPIECE);
break; break;
case AUDIO_POLICY_FORCE_SPEAKER: case AUDIO_POLICY_FORCE_SPEAKER:
@ -273,22 +263,18 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
if (!isInCall() && if (!isInCall() &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) && (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
outputs.isA2dpSupported()) { outputs.isA2dpSupported()) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; devices = availableOutputDevices.getDevicesFromTypeMask(
if (device) break; AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
if (!devices.isEmpty()) break;
} }
if (!isInCall()) { if (!isInCall()) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; devices = availableOutputDevices.getFirstDevicesFromTypes({
if (device) break; AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_AUX_DIGITAL,
if (device) break; AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; if (!devices.isEmpty()) break;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
} }
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
break; break;
} }
break; break;
@ -298,9 +284,8 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
// If incall, just select the STRATEGY_PHONE device // If incall, just select the STRATEGY_PHONE device
if (isInCall() || if (isInCall() ||
outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) { outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
device = getDeviceForStrategyInt( devices = getDevicesForStrategyInt(
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs, STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
outputDeviceTypesToIgnore);
break; break;
} }
FALLTHROUGH_INTENDED; FALLTHROUGH_INTENDED;
@ -313,41 +298,37 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
if ((strategy == STRATEGY_SONIFICATION) || if ((strategy == STRATEGY_SONIFICATION) ||
(getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) { (getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
} }
// if SCO headset is connected and we are told to use it, play ringtone over // if SCO headset is connected and we are told to use it, play ringtone over
// speaker and BT SCO // speaker and BT SCO
if ((availableOutputDevicesType & AUDIO_DEVICE_OUT_ALL_SCO) != 0) { if (!availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_ALL_SCO).isEmpty()) {
uint32_t device2 = AUDIO_DEVICE_NONE; DeviceVector devices2;
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; devices2 = availableOutputDevices.getFirstDevicesFromTypes({
if (device2 == AUDIO_DEVICE_NONE) { AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
}
// Use ONLY Bluetooth SCO output when ringing in vibration mode // Use ONLY Bluetooth SCO output when ringing in vibration mode
if (!((getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) if (!((getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
&& (strategy == STRATEGY_ENFORCED_AUDIBLE))) { && (strategy == STRATEGY_ENFORCED_AUDIBLE))) {
if (getForceUse(AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING) if (getForceUse(AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING)
== AUDIO_POLICY_FORCE_BT_SCO) { == AUDIO_POLICY_FORCE_BT_SCO) {
if (device2 != AUDIO_DEVICE_NONE) { if (!devices2.isEmpty()) {
device = device2; devices = devices2;
break; break;
} }
} }
} }
// Use both Bluetooth SCO and phone default output when ringing in normal mode // Use both Bluetooth SCO and phone default output when ringing in normal mode
if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) { if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) {
if ((strategy == STRATEGY_SONIFICATION) && if (strategy == STRATEGY_SONIFICATION) {
(device & AUDIO_DEVICE_OUT_SPEAKER) && devices.replaceDevicesByType(
(availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { AUDIO_DEVICE_OUT_SPEAKER,
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; availableOutputDevices.getDevicesFromTypeMask(
device &= ~AUDIO_DEVICE_OUT_SPEAKER; AUDIO_DEVICE_OUT_SPEAKER_SAFE));
} }
if (device2 != AUDIO_DEVICE_NONE) { if (!devices2.isEmpty()) {
device |= device2; devices.add(devices2);
break; break;
} }
} }
@ -361,25 +342,20 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
// compressed format as they would likely not be mixed and dropped. // compressed format as they would likely not be mixed and dropped.
for (size_t i = 0; i < outputs.size(); i++) { for (size_t i = 0; i < outputs.size(); i++) {
sp<AudioOutputDescriptor> desc = outputs.valueAt(i); sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
audio_devices_t devices = desc->devices().types() & if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) {
(AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC); availableOutputDevices.remove(desc->devices().getDevicesFromTypeMask(
if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) && AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF
devices != AUDIO_DEVICE_NONE) { | AUDIO_DEVICE_OUT_HDMI_ARC));
availableOutputDevicesType = availableOutputDevices.types() & ~devices;
} }
} }
availableOutputDevices =
availableOutputDevices.getDevicesFromTypeMask(availableOutputDevicesType);
if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) || if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) { outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) {
return getDeviceForStrategyInt( return getDevicesForStrategyInt(
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs, STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
outputDeviceTypesToIgnore);
} }
if (isInCall()) { if (isInCall()) {
return getDeviceForStrategyInt( return getDevicesForStrategyInt(
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs, STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
outputDeviceTypesToIgnore);
} }
} }
// For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA // For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA
@ -388,128 +364,116 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
// FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now // FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
case STRATEGY_REROUTING: case STRATEGY_REROUTING:
case STRATEGY_MEDIA: { case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE; DeviceVector devices2;
if (strategy != STRATEGY_SONIFICATION) { if (strategy != STRATEGY_SONIFICATION) {
// no sonification on remote submix (e.g. WFD) // no sonification on remote submix (e.g. WFD)
if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, sp<DeviceDescriptor> remoteSubmix;
String8("0"), AUDIO_FORMAT_DEFAULT) != 0) { if ((remoteSubmix = availableOutputDevices.getDevice(
device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX; AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0"),
AUDIO_FORMAT_DEFAULT)) != nullptr) {
devices2.add(remoteSubmix);
} }
} }
if (isInCall() && (strategy == STRATEGY_MEDIA)) { if (isInCall() && (strategy == STRATEGY_MEDIA)) {
device = getDeviceForStrategyInt( devices = getDevicesForStrategyInt(
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs, STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
outputDeviceTypesToIgnore);
break; break;
} }
// FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261). // FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261).
if ((device2 == AUDIO_DEVICE_NONE) && if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) { (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID; devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
} }
if ((device2 == AUDIO_DEVICE_NONE) && if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) && (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
outputs.isA2dpSupported()) { outputs.isA2dpSupported()) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; devices2 = availableOutputDevices.getFirstDevicesFromTypes({
if (device2 == AUDIO_DEVICE_NONE) { AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER});
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
}
} }
if ((device2 == AUDIO_DEVICE_NONE) && if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) { (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
} }
if (device2 == AUDIO_DEVICE_NONE) { if (devices2.isEmpty()) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; devices2 = availableOutputDevices.getFirstDevicesFromTypes({
AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_LINE,
AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET});
} }
if (device2 == AUDIO_DEVICE_NONE) { if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
}
if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
// no sonification on aux digital (e.g. HDMI) // no sonification on aux digital (e.g. HDMI)
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_AUX_DIGITAL);
} }
if ((device2 == AUDIO_DEVICE_NONE) && if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) { (getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; devices2 = availableOutputDevices.getDevicesFromTypeMask(
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
} }
if (device2 == AUDIO_DEVICE_NONE) { if (devices2.isEmpty()) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
} }
int device3 = AUDIO_DEVICE_NONE; DeviceVector devices3;
if (strategy == STRATEGY_MEDIA) { if (strategy == STRATEGY_MEDIA) {
// ARC, SPDIF and AUX_LINE can co-exist with others. // ARC, SPDIF and AUX_LINE can co-exist with others.
device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC; devices3 = availableOutputDevices.getDevicesFromTypeMask(
device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF); AUDIO_DEVICE_OUT_HDMI_ARC | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_AUX_LINE);
device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
} }
device2 |= device3; devices2.add(devices3);
// device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
// STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
device |= device2; devices.add(devices2);
// If hdmi system audio mode is on, remove speaker out of output list. // If hdmi system audio mode is on, remove speaker out of output list.
if ((strategy == STRATEGY_MEDIA) && if ((strategy == STRATEGY_MEDIA) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) == (getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) ==
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) { AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
device &= ~AUDIO_DEVICE_OUT_SPEAKER; devices.remove(devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
} }
// for STRATEGY_SONIFICATION: // for STRATEGY_SONIFICATION:
// if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead // if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
if ((strategy == STRATEGY_SONIFICATION) && if (strategy == STRATEGY_SONIFICATION) {
(device & AUDIO_DEVICE_OUT_SPEAKER) && devices.replaceDevicesByType(
(availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { AUDIO_DEVICE_OUT_SPEAKER,
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; availableOutputDevices.getDevicesFromTypeMask(
device &= ~AUDIO_DEVICE_OUT_SPEAKER; AUDIO_DEVICE_OUT_SPEAKER_SAFE));
} }
} break; } break;
default: default:
ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); ALOGW("getDevicesForStrategy() unknown strategy: %d", strategy);
break; break;
} }
if (device == AUDIO_DEVICE_NONE) { if (devices.isEmpty()) {
ALOGV("getDeviceForStrategy() no device found for strategy %d", strategy); ALOGV("getDevicesForStrategy() no device found for strategy %d", strategy);
device = getApmObserver()->getDefaultOutputDevice()->type(); sp<DeviceDescriptor> defaultOutputDevice = getApmObserver()->getDefaultOutputDevice();
ALOGE_IF(device == AUDIO_DEVICE_NONE, if (defaultOutputDevice != nullptr) {
"getDeviceForStrategy() no default device defined"); devices.add(defaultOutputDevice);
}
ALOGE_IF(devices.isEmpty(),
"getDevicesForStrategy() no default device defined");
} }
ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
return device; ALOGVV("getDevices"
"ForStrategy() strategy %d, device %x", strategy, devices.types());
return devices;
} }
audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource) const
{ {
const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices(); const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
const DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices(); const DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs(); const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; DeviceVector availableDevices = availableInputDevices;
sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput(); sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
audio_devices_t availablePrimaryDeviceTypes = availableInputDevices.getDeviceTypesFromHwModule( DeviceVector availablePrimaryDevices = availableInputDevices.getDevicesFromHwModule(
primaryOutput->getModuleHandle()) & ~AUDIO_DEVICE_BIT_IN; primaryOutput->getModuleHandle());
uint32_t device = AUDIO_DEVICE_NONE; sp<DeviceDescriptor> device;
// when a call is active, force device selection to match source VOICE_COMMUNICATION // when a call is active, force device selection to match source VOICE_COMMUNICATION
// for most other input sources to avoid rerouting call TX audio // for most other input sources to avoid rerouting call TX audio
@ -532,57 +496,47 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons
switch (inputSource) { switch (inputSource) {
case AUDIO_SOURCE_DEFAULT: case AUDIO_SOURCE_DEFAULT:
case AUDIO_SOURCE_MIC: case AUDIO_SOURCE_MIC:
if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) { device = availableDevices.getDevice(
device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP; AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
} else if ((getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) && if (device != nullptr) break;
(availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) { if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; device = availableDevices.getDevice(
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
device = AUDIO_DEVICE_IN_WIRED_HEADSET; if (device != nullptr) break;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) { }
device = AUDIO_DEVICE_IN_USB_HEADSET; device = availableDevices.getFirstExistingDevice({
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
device = AUDIO_DEVICE_IN_USB_DEVICE; AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { break;
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_SOURCE_VOICE_COMMUNICATION: case AUDIO_SOURCE_VOICE_COMMUNICATION:
// Allow only use of devices on primary input if in call and HAL does not support routing // Allow only use of devices on primary input if in call and HAL does not support routing
// to voice call path. // to voice call path.
if ((getPhoneState() == AUDIO_MODE_IN_CALL) && if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
(availableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) { (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX,
availableDeviceTypes = availablePrimaryDeviceTypes; String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) {
availableDevices = availablePrimaryDevices;
} }
switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) { switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
case AUDIO_POLICY_FORCE_BT_SCO: case AUDIO_POLICY_FORCE_BT_SCO:
// if SCO device is requested but no SCO device is available, fall back to default case // if SCO device is requested but no SCO device is available, fall back to default case
if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { device = availableDevices.getDevice(
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) {
break; break;
} }
FALLTHROUGH_INTENDED; FALLTHROUGH_INTENDED;
default: // FORCE_NONE default: // FORCE_NONE
if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { device = availableDevices.getFirstExistingDevice({
device = AUDIO_DEVICE_IN_WIRED_HEADSET; AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) { AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
device = AUDIO_DEVICE_IN_USB_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
device = AUDIO_DEVICE_IN_USB_DEVICE;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break; break;
case AUDIO_POLICY_FORCE_SPEAKER: case AUDIO_POLICY_FORCE_SPEAKER:
if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) { device = availableDevices.getFirstExistingDevice({
device = AUDIO_DEVICE_IN_BACK_MIC; AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break; break;
} }
break; break;
@ -591,77 +545,60 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons
case AUDIO_SOURCE_UNPROCESSED: case AUDIO_SOURCE_UNPROCESSED:
case AUDIO_SOURCE_HOTWORD: case AUDIO_SOURCE_HOTWORD:
if (inputSource == AUDIO_SOURCE_HOTWORD) { if (inputSource == AUDIO_SOURCE_HOTWORD) {
availableDeviceTypes = availablePrimaryDeviceTypes; availableDevices = availablePrimaryDevices;
} }
if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO && if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { device = availableDevices.getDevice(
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { if (device != nullptr) break;
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
device = AUDIO_DEVICE_IN_USB_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
device = AUDIO_DEVICE_IN_USB_DEVICE;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
} }
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
break; break;
case AUDIO_SOURCE_CAMCORDER: case AUDIO_SOURCE_CAMCORDER:
if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) { // For a device without built-in mic, adding usb device
device = AUDIO_DEVICE_IN_BACK_MIC; device = availableDevices.getFirstExistingDevice({
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
device = AUDIO_DEVICE_IN_BUILTIN_MIC; AUDIO_DEVICE_IN_USB_DEVICE});
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
// This is specifically for a device without built-in mic
device = AUDIO_DEVICE_IN_USB_DEVICE;
}
break; break;
case AUDIO_SOURCE_VOICE_DOWNLINK: case AUDIO_SOURCE_VOICE_DOWNLINK:
case AUDIO_SOURCE_VOICE_CALL: case AUDIO_SOURCE_VOICE_CALL:
case AUDIO_SOURCE_VOICE_UPLINK: case AUDIO_SOURCE_VOICE_UPLINK:
if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) { device = availableDevices.getDevice(
device = AUDIO_DEVICE_IN_VOICE_CALL; AUDIO_DEVICE_IN_VOICE_CALL, String8(""), AUDIO_FORMAT_DEFAULT);
}
break; break;
case AUDIO_SOURCE_VOICE_PERFORMANCE: case AUDIO_SOURCE_VOICE_PERFORMANCE:
if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { device = availableDevices.getFirstExistingDevice({
device = AUDIO_DEVICE_IN_WIRED_HEADSET; AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) { AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
device = AUDIO_DEVICE_IN_USB_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
device = AUDIO_DEVICE_IN_USB_DEVICE;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break; break;
case AUDIO_SOURCE_REMOTE_SUBMIX: case AUDIO_SOURCE_REMOTE_SUBMIX:
if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { device = availableDevices.getDevice(
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(""), AUDIO_FORMAT_DEFAULT);
}
break; break;
case AUDIO_SOURCE_FM_TUNER: case AUDIO_SOURCE_FM_TUNER:
if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) { device = availableDevices.getDevice(
device = AUDIO_DEVICE_IN_FM_TUNER; AUDIO_DEVICE_IN_FM_TUNER, String8(""), AUDIO_FORMAT_DEFAULT);
}
break; break;
case AUDIO_SOURCE_ECHO_REFERENCE: case AUDIO_SOURCE_ECHO_REFERENCE:
if (availableDeviceTypes & AUDIO_DEVICE_IN_ECHO_REFERENCE) { device = availableDevices.getDevice(
device = AUDIO_DEVICE_IN_ECHO_REFERENCE; AUDIO_DEVICE_IN_ECHO_REFERENCE, String8(""), AUDIO_FORMAT_DEFAULT);
}
break; break;
default: default:
ALOGW("getDeviceForInputSource() invalid input source %d", inputSource); ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
break; break;
} }
if (device == AUDIO_DEVICE_NONE) { if (device == nullptr) {
ALOGV("getDeviceForInputSource() no device found for source %d", inputSource); ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
if (availableDeviceTypes & AUDIO_DEVICE_IN_STUB) { device = availableDevices.getDevice(
device = AUDIO_DEVICE_IN_STUB; AUDIO_DEVICE_IN_STUB, String8(""), AUDIO_FORMAT_DEFAULT);
} ALOGE_IF(device == nullptr,
ALOGE_IF(device == AUDIO_DEVICE_NONE,
"getDeviceForInputSource() no default device defined"); "getDeviceForInputSource() no default device defined");
} }
ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device); ALOGV_IF(device != nullptr,
"getDeviceForInputSource()input source %d, device %08x",
inputSource, device->type());
return device; return device;
} }
@ -684,11 +621,9 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) c
auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ? auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
mLegacyStrategyMap.at(strategy) : STRATEGY_NONE; mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
audio_devices_t devices = getDeviceForStrategyInt(legacyStrategy, return getDevicesForStrategyInt(legacyStrategy,
availableOutputDevices, availableOutputDevices,
availableInputDevices, outputs, availableInputDevices, outputs);
(uint32_t)AUDIO_DEVICE_NONE);
return availableOutputDevices.getDevicesFromTypeMask(devices);
} }
DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes, DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
@ -747,17 +682,21 @@ sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_
if (device != nullptr) { if (device != nullptr) {
return device; return device;
} }
audio_devices_t deviceType = getDeviceForInputSource(attr.source);
if (audio_is_remote_submix_device(deviceType)) { device = getDeviceForInputSource(attr.source);
address = "0"; if (device == nullptr || !audio_is_remote_submix_device(device->type())) {
std::size_t pos; // Return immediately if the device is null or it is not a remote submix device.
std::string tags { attr.tags }; return device;
if ((pos = tags.find("addr=")) != std::string::npos) { }
address = tags.substr(pos + std::strlen("addr="));
} // For remote submix device, try to find the device by address.
address = "0";
std::size_t pos;
std::string tags { attr.tags };
if ((pos = tags.find("addr=")) != std::string::npos) {
address = tags.substr(pos + std::strlen("addr="));
} }
return availableInputDevices.getDevice(deviceType, return availableInputDevices.getDevice(device->type(),
String8(address.c_str()), String8(address.c_str()),
AUDIO_FORMAT_DEFAULT); AUDIO_FORMAT_DEFAULT);
} }

@ -73,15 +73,14 @@ private:
status_t setDefaultDevice(audio_devices_t device); status_t setDefaultDevice(audio_devices_t device);
audio_devices_t getDeviceForStrategyInt(legacy_strategy strategy, DeviceVector getDevicesForStrategyInt(legacy_strategy strategy,
DeviceVector availableOutputDevices, DeviceVector availableOutputDevices,
DeviceVector availableInputDevices, DeviceVector availableInputDevices,
const SwAudioOutputCollection &outputs, const SwAudioOutputCollection &outputs) const;
uint32_t outputDeviceTypesToIgnore) const;
DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const; DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const; sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
DeviceStrategyMap mDevicesForStrategies; DeviceStrategyMap mDevicesForStrategies;

@ -1206,9 +1206,9 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevices(
if (!desc->isDuplicated() && (profile == desc->mProfile)) { if (!desc->isDuplicated() && (profile == desc->mProfile)) {
// reuse direct output if currently open by the same client // reuse direct output if currently open by the same client
// and configured with same parameters // and configured with same parameters
if ((config->sample_rate == desc->mSamplingRate) && if ((config->sample_rate == desc->getSamplingRate()) &&
(config->format == desc->mFormat) && (config->format == desc->getFormat()) &&
(channelMask == desc->mChannelMask) && (channelMask == desc->getChannelMask()) &&
(session == desc->mDirectClientSession)) { (session == desc->mDirectClientSession)) {
desc->mDirectOpenCount++; desc->mDirectOpenCount++;
ALOGI("%s reusing direct output %d for session %d", __func__, ALOGI("%s reusing direct output %d for session %d", __func__,
@ -1248,13 +1248,13 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevices(
// only accept an output with the requested parameters // only accept an output with the requested parameters
if (status != NO_ERROR || if (status != NO_ERROR ||
(config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) || (config->sample_rate != 0 && config->sample_rate != outputDesc->getSamplingRate()) ||
(config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->mFormat) || (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->getFormat()) ||
(channelMask != 0 && channelMask != outputDesc->mChannelMask)) { (channelMask != 0 && channelMask != outputDesc->getChannelMask())) {
ALOGV("%s failed opening direct output: output %d sample rate %d %d," ALOGV("%s failed opening direct output: output %d sample rate %d %d,"
"format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate, "format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate,
outputDesc->mSamplingRate, config->format, outputDesc->mFormat, outputDesc->getSamplingRate(), config->format, outputDesc->getFormat(),
channelMask, outputDesc->mChannelMask); channelMask, outputDesc->getChannelMask());
if (output != AUDIO_IO_HANDLE_NONE) { if (output != AUDIO_IO_HANDLE_NONE) {
outputDesc->close(); outputDesc->close();
} }
@ -1525,13 +1525,13 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
// If haptic channel is specified, use the haptic output if present. // If haptic channel is specified, use the haptic output if present.
// When using haptic output, same audio format and sample rate are required. // When using haptic output, same audio format and sample rate are required.
const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask( const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask(
outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL); outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) { if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) {
continue; continue;
} }
if (outputHapticChannelCount >= hapticChannelCount if (outputHapticChannelCount >= hapticChannelCount
&& format == outputDesc->mFormat && format == outputDesc->getFormat()
&& samplingRate == outputDesc->mSamplingRate) { && samplingRate == outputDesc->getSamplingRate()) {
currentMatchCriteria[0] = outputHapticChannelCount; currentMatchCriteria[0] = outputHapticChannelCount;
} }
@ -1539,12 +1539,13 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags); currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags);
// channel mask and channel count match // channel mask and channel count match
uint32_t outputChannelCount = audio_channel_count_from_out_mask(outputDesc->mChannelMask); uint32_t outputChannelCount = audio_channel_count_from_out_mask(
outputDesc->getChannelMask());
if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 && if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 &&
channelCount <= outputChannelCount) { channelCount <= outputChannelCount) {
if ((audio_channel_mask_get_representation(channelMask) == if ((audio_channel_mask_get_representation(channelMask) ==
audio_channel_mask_get_representation(outputDesc->mChannelMask)) && audio_channel_mask_get_representation(outputDesc->getChannelMask())) &&
((channelMask & outputDesc->mChannelMask) == channelMask)) { ((channelMask & outputDesc->getChannelMask()) == channelMask)) {
currentMatchCriteria[2] = outputChannelCount; currentMatchCriteria[2] = outputChannelCount;
} }
currentMatchCriteria[3] = outputChannelCount; currentMatchCriteria[3] = outputChannelCount;
@ -1552,8 +1553,8 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
// sampling rate match // sampling rate match
if (samplingRate > SAMPLE_RATE_HZ_DEFAULT && if (samplingRate > SAMPLE_RATE_HZ_DEFAULT &&
samplingRate <= outputDesc->mSamplingRate) { samplingRate <= outputDesc->getSamplingRate()) {
currentMatchCriteria[4] = outputDesc->mSamplingRate; currentMatchCriteria[4] = outputDesc->getSamplingRate();
} }
// performance flags match // performance flags match
@ -1563,7 +1564,7 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
if (format != AUDIO_FORMAT_INVALID) { if (format != AUDIO_FORMAT_INVALID) {
currentMatchCriteria[6] = currentMatchCriteria[6] =
AudioPort::kFormatDistanceMax - AudioPort::kFormatDistanceMax -
AudioPort::formatDistance(format, outputDesc->mFormat); AudioPort::formatDistance(format, outputDesc->getFormat());
} }
// primary output match // primary output match
@ -2922,9 +2923,9 @@ status_t AudioPolicyManager::registerPolicyMixes(const Vector<AudioMix>& mixes)
// stereo and let audio flinger do the channel conversion if needed. // stereo and let audio flinger do the channel conversion if needed.
outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO; inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
rSubmixModule->addOutputProfile(address, &outputConfig, rSubmixModule->addOutputProfile(address.c_str(), &outputConfig,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address); AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
rSubmixModule->addInputProfile(address, &inputConfig, rSubmixModule->addInputProfile(address.c_str(), &inputConfig,
AUDIO_DEVICE_IN_REMOTE_SUBMIX, address); AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable, if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
@ -3020,8 +3021,8 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes)
} }
} }
} }
rSubmixModule->removeOutputProfile(address); rSubmixModule->removeOutputProfile(address.c_str());
rSubmixModule->removeInputProfile(address); rSubmixModule->removeInputProfile(address.c_str());
} else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) { } else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) { if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
@ -3233,7 +3234,7 @@ bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& conf
ALOGV("%s() profile %sfound with name: %s, " ALOGV("%s() profile %sfound with name: %s, "
"sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x", "sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x",
__FUNCTION__, profile != 0 ? "" : "NOT ", __FUNCTION__, profile != 0 ? "" : "NOT ",
(profile != 0 ? profile->getTagName().string() : "null"), (profile != 0 ? profile->getTagName().c_str() : "null"),
config.sample_rate, config.format, config.channel_mask, output_flags); config.sample_rate, config.format, config.channel_mask, output_flags);
return (profile != 0); return (profile != 0);
} }
@ -3897,7 +3898,7 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>
if (srcDevice->hasSameHwModuleAs(sinkDevice) && if (srcDevice->hasSameHwModuleAs(sinkDevice) &&
srcDevice->getModuleVersionMajor() >= 3 && srcDevice->getModuleVersionMajor() >= 3 &&
sinkDevice->getModule()->supportsPatch(srcDevice, sinkDevice) && sinkDevice->getModule()->supportsPatch(srcDevice, sinkDevice) &&
srcDevice->getAudioPort()->mGains.size() > 0) { srcDevice->getAudioPort()->getGains().size() > 0) {
ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__); ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__);
// TODO: may explicitly specify whether we should use HW or SW patch // TODO: may explicitly specify whether we should use HW or SW patch
// create patch between src device and output device // create patch between src device and output device
@ -4137,7 +4138,7 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat
for (size_t i = 0; i < hdmiOutputDevices.size(); i++) { for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats. // Simulate reconnection to update enabled surround sound formats.
String8 address = hdmiOutputDevices[i]->address(); String8 address = hdmiOutputDevices[i]->address();
String8 name = hdmiOutputDevices[i]->getName(); std::string name = hdmiOutputDevices[i]->getName();
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI, status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
address.c_str(), address.c_str(),
@ -4159,7 +4160,7 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat
for (size_t i = 0; i < hdmiInputDevices.size(); i++) { for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats. // Simulate reconnection to update enabled surround sound formats.
String8 address = hdmiInputDevices[i]->address(); String8 address = hdmiInputDevices[i]->address();
String8 name = hdmiInputDevices[i]->getName(); std::string name = hdmiInputDevices[i]->getName();
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI, status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
address.c_str(), address.c_str(),
@ -4642,7 +4643,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
} }
ALOGV("opening output for device %08x with params %s profile %p name %s", ALOGV("opening output for device %08x with params %s profile %p name %s",
deviceType, address.string(), profile.get(), profile->getName().string()); deviceType, address.string(), profile.get(), profile->getName().c_str());
desc = new SwAudioOutputDescriptor(profile, mpClientInterface); desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status = desc->open(nullptr, DeviceVector(device), status_t status = desc->open(nullptr, DeviceVector(device),

@ -38,7 +38,7 @@
#include <AudioPolicyConfig.h> #include <AudioPolicyConfig.h>
#include <AudioPort.h> #include <AudioPort.h>
#include <AudioPatch.h> #include <AudioPatch.h>
#include <AudioProfile.h> #include <AudioProfileVector.h>
#include <DeviceDescriptor.h> #include <DeviceDescriptor.h>
#include <IOProfile.h> #include <IOProfile.h>
#include <HwModule.h> #include <HwModule.h>

@ -396,12 +396,11 @@ void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) {
mMsdOutputDevice->attach(msdModule); mMsdOutputDevice->attach(msdModule);
mMsdInputDevice->attach(msdModule); mMsdInputDevice->attach(msdModule);
sp<OutputProfile> msdOutputProfile = new OutputProfile(String8("msd input")); sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
msdOutputProfile->addAudioProfile(pcmOutputProfile); msdOutputProfile->addAudioProfile(pcmOutputProfile);
msdOutputProfile->addSupportedDevice(mMsdOutputDevice); msdOutputProfile->addSupportedDevice(mMsdOutputDevice);
msdModule->addOutputProfile(msdOutputProfile); msdModule->addOutputProfile(msdOutputProfile);
sp<OutputProfile> msdCompressedOutputProfile = sp<OutputProfile> msdCompressedOutputProfile = new OutputProfile("msd compressed input");
new OutputProfile(String8("msd compressed input"));
msdCompressedOutputProfile->addAudioProfile(ac3OutputProfile); msdCompressedOutputProfile->addAudioProfile(ac3OutputProfile);
msdCompressedOutputProfile->setFlags( msdCompressedOutputProfile->setFlags(
AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
@ -409,7 +408,7 @@ void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) {
msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice); msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice);
msdModule->addOutputProfile(msdCompressedOutputProfile); msdModule->addOutputProfile(msdCompressedOutputProfile);
sp<InputProfile> msdInputProfile = new InputProfile(String8("msd output")); sp<InputProfile> msdInputProfile = new InputProfile("msd output");
msdInputProfile->addAudioProfile(pcmInputProfile); msdInputProfile->addAudioProfile(pcmInputProfile);
msdInputProfile->addSupportedDevice(mMsdInputDevice); msdInputProfile->addSupportedDevice(mMsdInputDevice);
msdModule->addInputProfile(msdInputProfile); msdModule->addInputProfile(msdInputProfile);
@ -419,7 +418,7 @@ void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) {
sp<AudioProfile> dtsOutputProfile = new AudioProfile( sp<AudioProfile> dtsOutputProfile = new AudioProfile(
AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000); AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000);
config->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile); config->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile(String8("encoded")); sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile("encoded");
primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile); primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT); primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
primaryEncodedOutputProfile->addSupportedDevice(config->getDefaultOutputDevice()); primaryEncodedOutputProfile->addSupportedDevice(config->getDefaultOutputDevice());

Loading…
Cancel
Save