Merge changes I70ebe6bc,I9a6d6401,Icbde26fe,I40299d95,Ifd8eb281, ...

* changes:
  Create DeviceDescriptorBase.
  Copy DeviceDescriptor to libaudiofoundation.
  Rename AudioPort and PolicyAudioPort accordingly.
  Make audio port in policy not derive from audio port base
  Rename AudioProfileVector.h as AudioProfileVectorHelper.h
  Leave AudioProfileVector only in libaudiofoundation.
gugelfrei
Treehugger Robot 5 years ago committed by Gerrit Code Review
commit f21a5174bc

@ -10,11 +10,13 @@ cc_library_shared {
srcs: [
"AudioGain.cpp",
"AudioPortBase.cpp",
"AudioPort.cpp",
"AudioProfile.cpp",
"DeviceDescriptorBase.cpp",
],
shared_libs: [
"libaudioutils",
"libbase",
"libbinder",
"liblog",

@ -0,0 +1,191 @@
/*
* 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.
*/
#define LOG_TAG "AudioPort"
#include <algorithm>
#include <android-base/stringprintf.h>
#include <media/AudioPort.h>
#include <utils/Log.h>
namespace android {
void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
{
for (const auto& profileToImport : port->mProfiles) {
// Import only valid port, i.e. valid format, non empty rates and channels masks
if (!profileToImport->isValid()) {
continue;
}
if (std::find_if(mProfiles.begin(), mProfiles.end(),
[profileToImport](const auto &profile) {
return *profile == *profileToImport; }) == mProfiles.end()) {
addAudioProfile(profileToImport);
}
}
}
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", __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 AudioPort::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;
mProfiles.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);
}
}
}
}
void AudioPort::log(const char* indent) const
{
ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
}
// --- AudioPortConfig class implementation
status_t AudioPortConfig::applyAudioPortConfig(
const struct audio_port_config *config,
struct audio_port_config *backupConfig __unused)
{
if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
mSamplingRate = config->sample_rate;
}
if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
mChannelMask = config->channel_mask;
}
if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
mFormat = config->format;
}
if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
mGain = config->gain;
}
return NO_ERROR;
}
namespace {
template<typename T>
void updateField(
const T& portConfigField, T audio_port_config::*port_config_field,
struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig,
unsigned int configMask, T defaultValue)
{
if (dstConfig->config_mask & configMask) {
if ((srcConfig != nullptr) && (srcConfig->config_mask & configMask)) {
dstConfig->*port_config_field = srcConfig->*port_config_field;
} else {
dstConfig->*port_config_field = portConfigField;
}
} else {
dstConfig->*port_config_field = defaultValue;
}
}
} // namespace
void AudioPortConfig::toAudioPortConfig(
struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
updateField(mSamplingRate, &audio_port_config::sample_rate,
dstConfig, srcConfig, AUDIO_PORT_CONFIG_SAMPLE_RATE, 0u);
updateField(mChannelMask, &audio_port_config::channel_mask,
dstConfig, srcConfig, AUDIO_PORT_CONFIG_CHANNEL_MASK,
(audio_channel_mask_t)AUDIO_CHANNEL_NONE);
updateField(mFormat, &audio_port_config::format,
dstConfig, srcConfig, AUDIO_PORT_CONFIG_FORMAT, AUDIO_FORMAT_INVALID);
dstConfig->id = mId;
sp<AudioPort> audioport = getAudioPort();
if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
dstConfig->gain = mGain;
if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
&& audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
dstConfig->gain = srcConfig->gain;
}
} else {
dstConfig->gain.index = -1;
}
if (dstConfig->gain.index != -1) {
dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
} else {
dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
}
}
bool AudioPortConfig::hasGainController(bool canUseForVolume) const
{
sp<AudioPort> audioport = getAudioPort();
if (!audioport) {
return false;
}
return canUseForVolume ? audioport->getGains().canUseForVolume()
: audioport->getGains().size() > 0;
}
}

@ -1,87 +0,0 @@
/*
* 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);
}
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* 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.
@ -118,14 +118,14 @@ void AudioProfile::dump(std::string *dst, int spaces) const
}
}
ssize_t AudioProfileVectorBase::add(const sp<AudioProfile> &profile)
ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
{
ssize_t index = size();
push_back(profile);
return index;
}
void AudioProfileVectorBase::clearProfiles()
void AudioProfileVector::clearProfiles()
{
for (auto it = begin(); it != end();) {
if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
@ -137,7 +137,7 @@ void AudioProfileVectorBase::clearProfiles()
}
}
sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfile() const
sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
{
for (const auto &profile : *this) {
if (profile->isValid()) {
@ -147,7 +147,7 @@ sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfile() const
return nullptr;
}
sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfileFor(audio_format_t format) const
sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->isValid() && profile->getFormat() == format) {
@ -157,7 +157,7 @@ sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfileFor(audio_format_t
return nullptr;
}
FormatVector AudioProfileVectorBase::getSupportedFormats() const
FormatVector AudioProfileVector::getSupportedFormats() const
{
FormatVector supportedFormats;
for (const auto &profile : *this) {
@ -168,7 +168,7 @@ FormatVector AudioProfileVectorBase::getSupportedFormats() const
return supportedFormats;
}
bool AudioProfileVectorBase::hasDynamicChannelsFor(audio_format_t format) const
bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->getFormat() == format && profile->isDynamicChannels()) {
@ -178,7 +178,7 @@ bool AudioProfileVectorBase::hasDynamicChannelsFor(audio_format_t format) const
return false;
}
bool AudioProfileVectorBase::hasDynamicFormat() const
bool AudioProfileVector::hasDynamicFormat() const
{
for (const auto &profile : *this) {
if (profile->isDynamicFormat()) {
@ -188,7 +188,7 @@ bool AudioProfileVectorBase::hasDynamicFormat() const
return false;
}
bool AudioProfileVectorBase::hasDynamicProfile() const
bool AudioProfileVector::hasDynamicProfile() const
{
for (const auto &profile : *this) {
if (profile->isDynamic()) {
@ -198,7 +198,7 @@ bool AudioProfileVectorBase::hasDynamicProfile() const
return false;
}
bool AudioProfileVectorBase::hasDynamicRateFor(audio_format_t format) const
bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->getFormat() == format && profile->isDynamicRate()) {
@ -208,7 +208,7 @@ bool AudioProfileVectorBase::hasDynamicRateFor(audio_format_t format) const
return false;
}
void AudioProfileVectorBase::dump(std::string *dst, int spaces) const
void AudioProfileVector::dump(std::string *dst, int spaces) const
{
dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, ""));
for (size_t i = 0; i < size(); i++) {

@ -0,0 +1,113 @@
/*
* 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.
*/
#define LOG_TAG "DeviceDescriptorBase"
//#define LOG_NDEBUG 0
#include <android-base/stringprintf.h>
#include <audio_utils/string.h>
#include <media/DeviceDescriptorBase.h>
#include <media/TypeConverter.h>
namespace android {
DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type) :
AudioPort("", AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE),
mDeviceType(type)
{
if (audio_is_remote_submix_device(type)) {
mAddress = "0";
}
}
void DeviceDescriptorBase::toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
dstConfig->config_mask = AUDIO_PORT_CONFIG_GAIN;
if (mSamplingRate != 0) {
dstConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
}
if (mChannelMask != AUDIO_CHANNEL_NONE) {
dstConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
}
if (mFormat != AUDIO_FORMAT_INVALID) {
dstConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
}
if (srcConfig != NULL) {
dstConfig->config_mask |= srcConfig->config_mask;
}
AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
dstConfig->role = audio_is_output_device(mDeviceType) ?
AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
dstConfig->ext.device.type = mDeviceType;
(void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.c_str());
}
void DeviceDescriptorBase::toAudioPort(struct audio_port *port) const
{
ALOGV("DeviceDescriptorBase::toAudioPort() handle %d type %08x", mId, mDeviceType);
AudioPort::toAudioPort(port);
toAudioPortConfig(&port->active_config);
port->id = mId;
port->ext.device.type = mDeviceType;
(void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.c_str());
}
void DeviceDescriptorBase::dump(std::string *dst, int spaces, int index,
const char* extraInfo, bool verbose) const
{
dst->append(base::StringPrintf("%*sDevice %d:\n", spaces, "", index + 1));
if (mId != 0) {
dst->append(base::StringPrintf("%*s- id: %2d\n", spaces, "", mId));
}
if (extraInfo != nullptr) {
dst->append(extraInfo);
}
dst->append(base::StringPrintf("%*s- type: %-48s\n",
spaces, "", ::android::toString(mDeviceType).c_str()));
if (mAddress.size() != 0) {
dst->append(base::StringPrintf("%*s- address: %-32s\n", spaces, "", mAddress.c_str()));
}
AudioPort::dump(dst, spaces, verbose);
}
std::string DeviceDescriptorBase::toString() const
{
std::stringstream sstream;
sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
return sstream.str();
}
void DeviceDescriptorBase::log() const
{
ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceType,
::android::toString(mDeviceType).c_str(),
mAddress.c_str());
AudioPort::log(" ");
}
} // namespace android

@ -27,13 +27,13 @@
namespace android {
class AudioPortFoundation : public virtual RefBase
class AudioPort : public virtual RefBase
{
public:
AudioPortFoundation(const std::string& 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) {}
virtual ~AudioPortFoundation() = default;
virtual ~AudioPort() = default;
void setName(const std::string &name) { mName = name; }
const std::string &getName() const { return mName; }
@ -41,22 +41,26 @@ public:
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);
mProfiles.add(profile);
}
virtual void clearAudioProfiles() {
getAudioProfileVectorBase()->clearProfiles();
mProfiles.clearProfiles();
}
bool hasValidAudioProfile() const { return getAudioProfileVectorBase()->hasValidProfile(); }
bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); }
bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); }
void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; }
AudioProfileVector &getAudioProfiles() { return mProfiles; }
virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
status_t checkGain(const struct audio_gain_config *gainConfig, int index) const {
if (index < 0 || (size_t)index >= mGains.size()) {
@ -73,57 +77,42 @@ public:
void dump(std::string *dst, int spaces, bool verbose = true) const;
void log(const char* indent) const;
AudioGains mGains; // gain controllers
protected:
std::string mName;
audio_port_type_t mType;
audio_port_role_t mRole;
AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
};
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
class AudioPortConfig : public virtual RefBase
{
public:
virtual ~AudioPortConfigBase() = default;
virtual ~AudioPortConfig() = default;
virtual sp<AudioPort> getAudioPort() const = 0;
virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
struct audio_port_config *backupConfig = NULL) = 0;
struct audio_port_config *backupConfig = NULL);
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;
unsigned int getSamplingRate() const { return mSamplingRate; }
audio_format_t getFormat() const { return mFormat; }
audio_channel_mask_t getChannelMask() const { return mChannelMask; }
audio_port_handle_t getId() const { return mId; }
bool hasGainController(bool canUseForVolume = false) const;
protected:
unsigned int mSamplingRate = 0u;
audio_format_t mFormat = AUDIO_FORMAT_INVALID;
audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
struct audio_gain_config mGain = { .index = -1 };
};

@ -77,10 +77,10 @@ private:
bool mIsDynamicRate = false;
};
class AudioProfileVectorBase : public std::vector<sp<AudioProfile> >
class AudioProfileVector : public std::vector<sp<AudioProfile>>
{
public:
virtual ~AudioProfileVectorBase() = default;
virtual ~AudioProfileVector() = default;
virtual ssize_t add(const sp<AudioProfile> &profile);

@ -0,0 +1,59 @@
/*
* 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 <media/AudioPort.h>
#include <utils/Errors.h>
#include <cutils/config_utils.h>
#include <system/audio.h>
#include <system/audio_policy.h>
namespace android {
class DeviceDescriptorBase : public AudioPort, public AudioPortConfig
{
public:
// Note that empty name refers by convention to a generic device.
explicit DeviceDescriptorBase(audio_devices_t type);
virtual ~DeviceDescriptorBase() {}
audio_devices_t type() const { return mDeviceType; }
std::string address() const { return mAddress; }
void setAddress(const std::string &address) { mAddress = address; }
// AudioPortConfig
virtual sp<AudioPort> getAudioPort() const {
return static_cast<AudioPort*>(const_cast<DeviceDescriptorBase*>(this));
}
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
// AudioPort
virtual void toAudioPort(struct audio_port *port) const;
void dump(std::string *dst, int spaces, int index,
const char* extraInfo = nullptr, bool verbose = true) const;
void log() const;
std::string toString() const;
protected:
std::string mAddress{""};
audio_devices_t mDeviceType;
};
} // namespace android

@ -7,14 +7,14 @@ cc_library_static {
"src/AudioOutputDescriptor.cpp",
"src/AudioPatch.cpp",
"src/AudioPolicyMix.cpp",
"src/AudioPort.cpp",
"src/AudioProfileVector.cpp",
"src/AudioProfileVectorHelper.cpp",
"src/AudioRoute.cpp",
"src/ClientDescriptor.cpp",
"src/DeviceDescriptor.cpp",
"src/EffectDescriptor.cpp",
"src/HwModule.cpp",
"src/IOProfile.cpp",
"src/PolicyAudioPort.cpp",
"src/Serializer.cpp",
"src/SoundTriggerSession.cpp",
"src/TypeConverter.cpp",

@ -25,20 +25,15 @@
namespace android {
class AudioPort;
class PolicyAudioPort;
class AudioRoute;
class AudioPortVector : public Vector<sp<AudioPort> >
{
public:
sp<AudioPort> findByTagName(const std::string &tagName) const;
};
using PolicyAudioPortVector = Vector<sp<PolicyAudioPort>>;
using AudioRouteVector = Vector<sp<AudioRoute>>;
sp<PolicyAudioPort> findByTagName(const PolicyAudioPortVector& policyAudioPortVector,
const std::string &tagName);
class AudioRouteVector : public Vector<sp<AudioRoute> >
{
public:
void dump(String8 *dst, int spaces) const;
};
void dumpAudioRouteVector(const AudioRouteVector& audioRouteVector, String8 *dst, int spaces);
} // namespace android

@ -21,11 +21,11 @@
#include <utils/SortedVector.h>
#include <utils/KeyedVector.h>
#include "AudioIODescriptorInterface.h"
#include "AudioPort.h"
#include "ClientDescriptor.h"
#include "DeviceDescriptor.h"
#include "EffectDescriptor.h"
#include "IOProfile.h"
#include "PolicyAudioPort.h"
namespace android {
@ -34,13 +34,17 @@ class AudioPolicyClientInterface;
// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
// and keep track of the usage of this input.
class AudioInputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
, public ClientMapHandler<RecordClientDescriptor>
class AudioInputDescriptor: public AudioPortConfig,
public PolicyAudioPortConfig,
public AudioIODescriptorInterface,
public ClientMapHandler<RecordClientDescriptor>
{
public:
explicit AudioInputDescriptor(const sp<IOProfile>& profile,
AudioPolicyClientInterface *clientInterface);
audio_port_handle_t getId() const;
AudioInputDescriptor(const sp<IOProfile>& profile,
AudioPolicyClientInterface *clientInterface);
virtual ~AudioInputDescriptor() = default;
audio_module_handle_t getModuleHandle() const;
audio_devices_t getDeviceType() const { return (mDevice != nullptr) ?
@ -56,9 +60,18 @@ public:
wp<AudioPolicyMix> mPolicyMix; // non NULL when used by a dynamic policy
const sp<IOProfile> mProfile; // I/O profile this output derives from
// PolicyAudioPortConfig
virtual sp<PolicyAudioPort> getPolicyAudioPort() const {
return mProfile;
}
// AudioPortConfig
virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
struct audio_port_config *backupConfig = NULL);
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
virtual sp<AudioPort> getAudioPort() const { return mProfile; }
void toAudioPort(struct audio_port *port) const;
void setPreemptedSessions(const SortedVector<audio_session_t>& sessions);
SortedVector<audio_session_t> getPreemptedSessions() const;
@ -111,7 +124,6 @@ public:
void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
sp<DeviceDescriptor> mDevice = nullptr; /**< current device this input is routed to */
// Because a preemptible capture session can preempt another one, we end up in an endless loop

@ -26,9 +26,9 @@
#include <utils/KeyedVector.h>
#include <system/audio.h>
#include "AudioIODescriptorInterface.h"
#include "AudioPort.h"
#include "ClientDescriptor.h"
#include "DeviceDescriptor.h"
#include "PolicyAudioPort.h"
#include <vector>
namespace android {
@ -138,18 +138,19 @@ using RoutingActivities = std::map<product_strategy_t, RoutingActivity>;
// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
class AudioOutputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
, public ClientMapHandler<TrackClientDescriptor>
class AudioOutputDescriptor: public AudioPortConfig,
public PolicyAudioPortConfig,
public AudioIODescriptorInterface,
public ClientMapHandler<TrackClientDescriptor>
{
public:
AudioOutputDescriptor(const sp<AudioPort>& port,
AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
AudioPolicyClientInterface *clientInterface);
virtual ~AudioOutputDescriptor() {}
void dump(String8 *dst) const override;
void log(const char* indent);
audio_port_handle_t getId() const;
virtual DeviceVector devices() const { return mDevices; }
bool sharesHwModuleWith(const sp<AudioOutputDescriptor>& outputDesc);
virtual DeviceVector supportedDevices() const { return mDevices; }
@ -245,9 +246,19 @@ public:
mRoutingActivities[ps].setMutedByDevice(isMuted);
}
// PolicyAudioPortConfig
virtual sp<PolicyAudioPort> getPolicyAudioPort() const
{
return mPolicyAudioPort;
}
// AudioPortConfig
virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
struct audio_port_config *backupConfig = NULL);
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
virtual sp<AudioPort> getAudioPort() const { return mPort; }
virtual sp<AudioPort> getAudioPort() const { return mPolicyAudioPort->asAudioPort(); }
virtual void toAudioPort(struct audio_port *port) const;
audio_module_handle_t getModuleHandle() const;
@ -289,11 +300,10 @@ public:
wp<AudioPolicyMix> mPolicyMix; // non NULL when used by a dynamic policy
protected:
const sp<AudioPort> mPort;
const sp<PolicyAudioPort> mPolicyAudioPort;
AudioPolicyClientInterface * const mClientInterface;
uint32_t mGlobalActiveCount = 0; // non-client-specific active count
audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
// The ActiveClients shows the clients that contribute to the @VolumeSource counts
// and may include upstream clients from a duplicating thread.

@ -19,11 +19,11 @@
#include <unordered_map>
#include <unordered_set>
#include <AudioPort.h>
#include <AudioPatch.h>
#include <DeviceDescriptor.h>
#include <IOProfile.h>
#include <HwModule.h>
#include <PolicyAudioPort.h>
#include <AudioInputDescriptor.h>
#include <AudioOutputDescriptor.h>
#include <AudioPolicyMix.h>

@ -1,68 +0,0 @@
/*
* 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

@ -0,0 +1,67 @@
/*
* 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 {
void sortAudioProfiles(AudioProfileVector &audioProfileVector);
ssize_t addAudioProfileAndSort(AudioProfileVector &audioProfileVector,
const sp<AudioProfile> &profile);
// One audio profile will be added for each format supported by Audio HAL
void addProfilesForFormats(AudioProfileVector &audioProfileVector,
const FormatVector &formatVector);
// This API is intended to be used by the policy manager once retrieving capabilities
// for a profile with dynamic format, rate and channels attributes
void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector,
const sp<AudioProfile> &profileToAdd);
void appendAudioProfiles(AudioProfileVector &audioProfileVector,
const AudioProfileVector &audioProfileVectorToAppend);
status_t checkExactProfile(const AudioProfileVector &audioProfileVector,
const uint32_t samplingRate,
audio_channel_mask_t channelMask,
audio_format_t format);
status_t checkCompatibleProfile(const AudioProfileVector &audioProfileVector,
uint32_t &samplingRate,
audio_channel_mask_t &channelMask,
audio_format_t &format,
audio_port_type_t portType,
audio_port_role_t portRole);
// 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 &audioProfileVector,
const AudioProfileVector &outputProfileVector,
const std::vector<audio_format_t> &preferredFormatVector, // order: most pref -> least pref
const std::vector<audio_channel_mask_t> &preferredOutputChannelVector,
bool preferHigherSamplingRates,
audio_config_base &bestOutputConfig);
} // namespace android

@ -25,7 +25,7 @@
namespace android
{
class AudioPort;
class PolicyAudioPort;
class DeviceDescriptor;
typedef enum {
@ -38,11 +38,11 @@ class AudioRoute : public virtual RefBase
public:
explicit AudioRoute(audio_route_type_t type) : mType(type) {}
void setSources(const AudioPortVector &sources) { mSources = sources; }
const AudioPortVector &getSources() const { return mSources; }
void setSources(const PolicyAudioPortVector &sources) { mSources = sources; }
const PolicyAudioPortVector &getSources() const { return mSources; }
void setSink(const sp<AudioPort> &sink) { mSink = sink; }
const sp<AudioPort> &getSink() const { return mSink; }
void setSink(const sp<PolicyAudioPort> &sink) { mSink = sink; }
const sp<PolicyAudioPort> &getSink() const { return mSink; }
audio_route_type_t getType() const { return mType; }
@ -57,13 +57,14 @@ public:
* @return true if the audio route supports the connection between the sink and the source,
* false otherwise
*/
bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
bool supportsPatch(const sp<PolicyAudioPort> &srcPort,
const sp<PolicyAudioPort> &dstPort) const;
void dump(String8 *dst, int spaces) const;
private:
AudioPortVector mSources;
sp<AudioPort> mSink;
PolicyAudioPortVector mSources;
sp<PolicyAudioPort> mSink;
audio_route_type_t mType;
};

@ -16,7 +16,8 @@
#pragma once
#include "AudioPort.h"
#include "PolicyAudioPort.h"
#include <media/DeviceDescriptorBase.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <utils/SortedVector.h>
@ -26,7 +27,8 @@
namespace android {
class DeviceDescriptor : public AudioPort, public AudioPortConfig
class DeviceDescriptor : public DeviceDescriptorBase,
public PolicyAudioPort, public PolicyAudioPortConfig
{
public:
// Note that empty name refers by convention to a generic device.
@ -36,11 +38,11 @@ public:
virtual ~DeviceDescriptor() {}
virtual const std::string getTagName() const { return mTagName; }
virtual void addAudioProfile(const sp<AudioProfile> &profile) {
addAudioProfileAndSort(mProfiles, profile);
}
audio_devices_t type() const { return mDeviceType; }
String8 address() const { return mAddress; }
void setAddress(const String8 &address) { mAddress = address; }
virtual const std::string getTagName() const { return mTagName; }
const FormatVector& encodedFormats() const { return mEncodedFormats; }
@ -56,29 +58,35 @@ public:
bool supportsFormat(audio_format_t format);
// PolicyAudioPortConfig
virtual sp<PolicyAudioPort> getPolicyAudioPort() const {
return static_cast<PolicyAudioPort*>(const_cast<DeviceDescriptor*>(this));
}
// AudioPortConfig
virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
struct audio_port_config *backupConfig = NULL);
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
// AudioPort
// PolicyAudioPort
virtual sp<AudioPort> asAudioPort() const {
return static_cast<AudioPort*>(const_cast<DeviceDescriptor*>(this));
}
virtual void attach(const sp<HwModule>& module);
virtual void detach();
// AudioPort
virtual void toAudioPort(struct audio_port *port) const;
virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
audio_port_handle_t getId() const;
void importAudioPortAndPickAudioProfile(const sp<PolicyAudioPort>& policyPort,
bool force = false);
void dump(String8 *dst, int spaces, int index, bool verbose = true) const;
void log() const;
std::string toString() const;
private:
String8 mAddress{""};
std::string mTagName; // Unique human readable identifier for a device port found in conf file.
audio_devices_t mDeviceType;
FormatVector mEncodedFormats;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
audio_format_t mCurrentEncodedFormat;
};
@ -203,7 +211,7 @@ public:
{
for (const auto &device : *this) {
if (device->address() != "") {
return device->address();
return String8(device->address().c_str());
}
}
return String8("");

@ -92,9 +92,9 @@ public:
audio_module_handle_t getHandle() const { return mHandle; }
void setHandle(audio_module_handle_t handle);
sp<AudioPort> findPortByTagName(const std::string &tagName) const
sp<PolicyAudioPort> findPortByTagName(const std::string &tagName) const
{
return mPorts.findByTagName(tagName);
return findByTagName(mPorts, tagName);
}
/**
@ -106,7 +106,8 @@ public:
* @return true if the HwModule supports the connection between the sink and the source,
* false otherwise
*/
bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
bool supportsPatch(const sp<PolicyAudioPort> &srcPort,
const sp<PolicyAudioPort> &dstPort) const;
// TODO remove from here (split serialization)
void dump(String8 *dst) const;
@ -122,7 +123,7 @@ private:
DeviceVector mDeclaredDevices; // devices declared in audio_policy configuration file.
DeviceVector mDynamicDevices; /**< devices that can be added/removed at runtime (e.g. rsbumix)*/
AudioRouteVector mRoutes;
AudioPortVector mPorts;
PolicyAudioPortVector mPorts;
};
class HwModuleCollection : public Vector<sp<HwModule> >

@ -16,8 +16,8 @@
#pragma once
#include "AudioPort.h"
#include "DeviceDescriptor.h"
#include "PolicyAudioPort.h"
#include "policy.h"
#include <utils/String8.h>
#include <system/audio.h>
@ -31,7 +31,7 @@ class HwModule;
// It is used by the policy manager to determine if an output or input is suitable for
// a given use case, open/close it accordingly and connect/disconnect audio tracks
// to/from it.
class IOProfile : public AudioPort
class IOProfile : public AudioPort, public PolicyAudioPort
{
public:
IOProfile(const std::string &name, audio_port_role_t role)
@ -41,9 +41,19 @@ public:
maxActiveCount(1),
curActiveCount(0) {}
virtual ~IOProfile() = default;
// For a Profile aka MixPort, tag name and name are equivalent.
virtual const std::string getTagName() const { return getName(); }
virtual void addAudioProfile(const sp<AudioProfile> &profile) {
addAudioProfileAndSort(mProfiles, profile);
}
virtual sp<AudioPort> asAudioPort() const {
return static_cast<AudioPort*>(const_cast<IOProfile*>(this));
}
// 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
// MMAP no IRQ input streams do not have the default limitation of one active client
@ -52,7 +62,7 @@ public:
// flags are parsed before maxActiveCount by the serializer.
void setFlags(uint32_t flags) override
{
AudioPort::setFlags(flags);
PolicyAudioPort::setFlags(flags);
if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
maxActiveCount = 0;
}

@ -17,10 +17,10 @@
#pragma once
#include "AudioCollections.h"
#include "AudioProfileVector.h"
#include "AudioProfileVectorHelper.h"
#include "HandleGenerator.h"
#include <media/AudioGain.h>
#include <media/AudioPortBase.h>
#include <media/AudioPort.h>
#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/RefBase.h>
@ -33,21 +33,24 @@ namespace android {
class HwModule;
class AudioRoute;
class AudioPort : public virtual RefBase, public AudioPortBase<AudioProfileVector>,
private HandleGenerator<audio_port_handle_t>
class PolicyAudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
{
public:
AudioPort(const std::string& name, audio_port_type_t type, audio_port_role_t role) :
AudioPortBase(name, type, role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
PolicyAudioPort() : mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
virtual ~AudioPort() {}
virtual ~PolicyAudioPort() = default;
virtual const std::string getTagName() const = 0;
virtual sp<AudioPort> asAudioPort() const = 0;
virtual void setFlags(uint32_t flags)
{
//force direct flag if offload flag is set: offloading implies a direct output stream
// and all common behaviors are driven by checking only the direct flag
// this should normally be set appropriately in the policy configuration file
if (mRole == AUDIO_PORT_ROLE_SOURCE && (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
if (asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE &&
(flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
flags |= AUDIO_OUTPUT_FLAG_DIRECT;
}
mFlags = flags;
@ -61,10 +64,6 @@ public:
// Audio port IDs are in a different namespace than AudioFlinger unique IDs
static audio_port_handle_t getNextUniqueId();
virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
bool hasDynamicAudioProfile() const { return getAudioProfileVectorBase()->hasDynamicProfile(); }
// searches for an exact match
virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
@ -74,7 +73,9 @@ public:
audio_channel_mask_t &channelMask,
audio_format_t &format) const
{
return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole);
return checkCompatibleProfile(
asAudioPort()->getAudioProfiles(), samplingRate, channelMask, format,
asAudioPort()->getType(), asAudioPort()->getRole());
}
void pickAudioProfile(uint32_t &samplingRate,
@ -101,15 +102,14 @@ public:
inline bool isDirectOutput() const
{
return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) &&
(asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
(mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
}
void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
const AudioRouteVector &getRoutes() const { return mRoutes; }
void log(const char* indent) const;
private:
void pickChannelMask(audio_channel_mask_t &channelMask,
const ChannelMaskSet &channelMasks) const;
@ -120,23 +120,32 @@ private:
AudioRouteVector mRoutes; // Routes involving this port
};
class AudioPortConfig : public AudioPortConfigBase
class PolicyAudioPortConfig : public virtual RefBase
{
public:
status_t applyAudioPortConfig(const struct audio_port_config *config,
struct audio_port_config *backupConfig = NULL) override;
virtual ~PolicyAudioPortConfig() = default;
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const override;
virtual sp<PolicyAudioPort> getPolicyAudioPort() const = 0;
virtual sp<AudioPort> getAudioPort() const = 0;
status_t validationBeforeApplyConfig(const struct audio_port_config *config) const;
virtual bool hasSameHwModuleAs(const sp<AudioPortConfig>& other) const {
return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) &&
(other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
void applyPolicyAudioPortConfig(const struct audio_port_config *config) {
if (config->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
mFlags = config->flags;
}
}
bool hasGainController(bool canUseForVolume = false) const;
void toPolicyAudioPortConfig(
struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
virtual bool hasSameHwModuleAs(const sp<PolicyAudioPortConfig>& other) const {
return (other.get() != nullptr) && (other->getPolicyAudioPort().get() != nullptr) &&
(getPolicyAudioPort().get() != nullptr) &&
(other->getPolicyAudioPort()->getModuleHandle() ==
getPolicyAudioPort()->getModuleHandle());
}
union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
};

@ -18,15 +18,16 @@
//#define LOG_NDEBUG 0
#include "AudioCollections.h"
#include "AudioPort.h"
#include "AudioRoute.h"
#include "HwModule.h"
#include "PolicyAudioPort.h"
namespace android {
sp<AudioPort> AudioPortVector::findByTagName(const std::string &tagName) const
sp<PolicyAudioPort> findByTagName(const PolicyAudioPortVector& policyAudioPortVector,
const std::string &tagName)
{
for (const auto& port : *this) {
for (const auto& port : policyAudioPortVector) {
if (port->getTagName() == tagName) {
return port;
}
@ -34,15 +35,15 @@ sp<AudioPort> AudioPortVector::findByTagName(const std::string &tagName) const
return nullptr;
}
void AudioRouteVector::dump(String8 *dst, int spaces) const
void dumpAudioRouteVector(const AudioRouteVector& audioRouteVector, String8 *dst, int spaces)
{
if (isEmpty()) {
if (audioRouteVector.isEmpty()) {
return;
}
dst->appendFormat("\n%*sAudio Routes (%zu):\n", spaces, "", size());
for (size_t i = 0; i < size(); i++) {
dst->appendFormat("\n%*sAudio Routes (%zu):\n", spaces, "", audioRouteVector.size());
for (size_t i = 0; i < audioRouteVector.size(); i++) {
dst->appendFormat("%*s- Route %zu:\n", spaces, "", i + 1);
itemAt(i)->dump(dst, 4);
audioRouteVector.itemAt(i)->dump(dst, 4);
}
}

@ -48,14 +48,27 @@ audio_module_handle_t AudioInputDescriptor::getModuleHandle() const
return mProfile->getModuleHandle();
}
audio_port_handle_t AudioInputDescriptor::getId() const
audio_source_t AudioInputDescriptor::source() const
{
return mId;
return getHighestPriorityAttributes().source;
}
audio_source_t AudioInputDescriptor::source() const
status_t AudioInputDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
audio_port_config *backupConfig)
{
return getHighestPriorityAttributes().source;
struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
status_t status = NO_ERROR;
toAudioPortConfig(&localBackupConfig);
if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
AudioPortConfig::applyAudioPortConfig(config, backupConfig);
applyPolicyAudioPortConfig(config);
}
if (backupConfig != NULL) {
*backupConfig = localBackupConfig;
}
return status;
}
void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
@ -70,8 +83,8 @@ void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig
}
AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
toPolicyAudioPortConfig(dstConfig, srcConfig);
dstConfig->id = mId;
dstConfig->role = AUDIO_PORT_ROLE_SINK;
dstConfig->type = AUDIO_PORT_TYPE_MIX;
dstConfig->ext.mix.hw_module = getModuleHandle();
@ -220,7 +233,7 @@ status_t AudioInputDescriptor::open(const audio_config_t *config,
input,
&lConfig,
&deviceType,
mDevice->address(),
String8(mDevice->address().c_str()),
source,
flags);
LOG_ALWAYS_FATAL_IF(mDevice->type() != deviceType,
@ -234,7 +247,7 @@ status_t AudioInputDescriptor::open(const audio_config_t *config,
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
mId = AudioPort::getNextUniqueId();
mId = PolicyAudioPort::getNextUniqueId();
mIoHandle = *input;
mProfile->curOpenCount++;
}

@ -34,14 +34,14 @@
namespace android {
AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
AudioOutputDescriptor::AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
AudioPolicyClientInterface *clientInterface)
: mPort(port), mClientInterface(clientInterface)
: mPolicyAudioPort(policyAudioPort), mClientInterface(clientInterface)
{
if (mPort.get() != nullptr) {
mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
if (mPort->getGains().size() > 0) {
mPort->getGains()[0]->getDefaultConfig(&mGain);
if (mPolicyAudioPort.get() != nullptr) {
mPolicyAudioPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
if (mPolicyAudioPort->asAudioPort()->getGains().size() > 0) {
mPolicyAudioPort->asAudioPort()->getGains()[0]->getDefaultConfig(&mGain);
}
}
}
@ -55,7 +55,8 @@ audio_config_base_t AudioOutputDescriptor::getConfig() const
audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
{
return mPort.get() != nullptr ? mPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE;
return mPolicyAudioPort.get() != nullptr ?
mPolicyAudioPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE;
}
audio_patch_handle_t AudioOutputDescriptor::getPatchHandle() const
@ -68,11 +69,6 @@ void AudioOutputDescriptor::setPatchHandle(audio_patch_handle_t handle)
mPatchHandle = handle;
}
audio_port_handle_t AudioOutputDescriptor::getId() const
{
return mId;
}
bool AudioOutputDescriptor::sharesHwModuleWith(
const sp<AudioOutputDescriptor>& outputDesc)
{
@ -167,9 +163,27 @@ bool AudioOutputDescriptor::setVolume(float volumeDb,
return false;
}
void AudioOutputDescriptor::toAudioPortConfig(
struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
status_t AudioOutputDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
audio_port_config *backupConfig)
{
struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
status_t status = NO_ERROR;
toAudioPortConfig(&localBackupConfig);
if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
AudioPortConfig::applyAudioPortConfig(config, backupConfig);
applyPolicyAudioPortConfig(config);
}
if (backupConfig != NULL) {
*backupConfig = localBackupConfig;
}
return status;
}
void AudioOutputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
@ -177,8 +191,8 @@ void AudioOutputDescriptor::toAudioPortConfig(
dstConfig->config_mask |= srcConfig->config_mask;
}
AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
toPolicyAudioPortConfig(dstConfig, srcConfig);
dstConfig->id = mId;
dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
dstConfig->type = AUDIO_PORT_TYPE_MIX;
dstConfig->ext.mix.hw_module = getModuleHandle();
@ -188,7 +202,7 @@ void AudioOutputDescriptor::toAudioPortConfig(
void AudioOutputDescriptor::toAudioPort(struct audio_port *port) const
{
// Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig.
mPort->toAudioPort(port);
mPolicyAudioPort->asAudioPort()->toAudioPort(port);
port->id = mId;
port->ext.mix.hw_module = getModuleHandle();
}
@ -503,7 +517,7 @@ status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
mId = AudioPort::getNextUniqueId();
mId = PolicyAudioPort::getNextUniqueId();
mIoHandle = *output;
mProfile->curOpenCount++;
}
@ -589,7 +603,7 @@ status_t SwAudioOutputDescriptor::openDuplicating(const sp<SwAudioOutputDescript
return INVALID_OPERATION;
}
mId = AudioPort::getNextUniqueId();
mId = PolicyAudioPort::getNextUniqueId();
mIoHandle = *ioHandle;
mOutput1 = output1;
mOutput2 = output2;

@ -20,7 +20,7 @@
#include "AudioPolicyMix.h"
#include "TypeConverter.h"
#include "HwModule.h"
#include "AudioPort.h"
#include "PolicyAudioPort.h"
#include "IOProfile.h"
#include <AudioOutputDescriptor.h>

@ -18,22 +18,155 @@
#include <set>
#include <string>
#define LOG_TAG "APM::AudioProfile"
#define LOG_TAG "APM::AudioProfileVectorHelper"
//#define LOG_NDEBUG 0
#include <media/AudioContainers.h>
#include <media/AudioResamplerPublic.h>
#include <utils/Errors.h>
#include "AudioPort.h"
#include "AudioProfileVector.h"
#include "AudioProfileVectorHelper.h"
#include "HwModule.h"
#include "PolicyAudioPort.h"
#include "policy.h"
namespace android {
status_t checkExact(const sp<AudioProfile> &audioProfile, uint32_t samplingRate,
audio_channel_mask_t channelMask, audio_format_t format)
void sortAudioProfiles(AudioProfileVector &audioProfileVector) {
std::sort(audioProfileVector.begin(), audioProfileVector.end(),
[](const sp<AudioProfile> & a, const sp<AudioProfile> & b)
{
return PolicyAudioPort::compareFormats(a->getFormat(), b->getFormat()) < 0;
});
}
ssize_t addAudioProfileAndSort(AudioProfileVector &audioProfileVector,
const sp<AudioProfile> &profile)
{
ssize_t ret = audioProfileVector.add(profile);
// we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry.
sortAudioProfiles(audioProfileVector);
return ret;
}
sp<AudioProfile> getAudioProfileForFormat(const AudioProfileVector &audioProfileVector,
audio_format_t format)
{
for (const auto &profile : audioProfileVector) {
if (profile->getFormat() == format) {
return profile;
}
}
return nullptr;
}
void setSampleRatesForAudioProfiles(AudioProfileVector &audioProfileVector,
const SampleRateSet &sampleRateSet,
audio_format_t format)
{
for (const auto &profile : audioProfileVector) {
if (profile->getFormat() == format && profile->isDynamicRate()) {
if (profile->hasValidRates()) {
// Need to create a new profile with same format
sp<AudioProfile> profileToAdd = new AudioProfile(
format, profile->getChannels(), sampleRateSet);
profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
addAudioProfileAndSort(audioProfileVector, profileToAdd);
} else {
profile->setSampleRates(sampleRateSet);
}
return;
}
}
}
void setChannelsForAudioProfiles(AudioProfileVector &audioProfileVector,
const ChannelMaskSet &channelMaskSet,
audio_format_t format)
{
for (const auto &profile : audioProfileVector) {
if (profile->getFormat() == format && profile->isDynamicChannels()) {
if (profile->hasValidChannels()) {
// Need to create a new profile with same format
sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMaskSet,
profile->getSampleRates());
profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
addAudioProfileAndSort(audioProfileVector, profileToAdd);
} else {
profile->setChannels(channelMaskSet);
}
return;
}
}
}
void addProfilesForFormats(AudioProfileVector &audioProfileVector, const FormatVector &formatVector)
{
// Only allow to change the format of dynamic profile
sp<AudioProfile> dynamicFormatProfile = getAudioProfileForFormat(
audioProfileVector, gDynamicFormat);
if (!dynamicFormatProfile) {
return;
}
for (const auto &format : formatVector) {
sp<AudioProfile> profile = new AudioProfile(format,
dynamicFormatProfile->getChannels(),
dynamicFormatProfile->getSampleRates());
profile->setDynamicFormat(true);
profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels());
profile->setDynamicRate(dynamicFormatProfile->isDynamicRate());
addAudioProfileAndSort(audioProfileVector, profile);
}
}
void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector,
const sp<AudioProfile> &profileToAdd)
{
// Check valid profile to add:
if (!profileToAdd->hasValidFormat()) {
ALOGW("Adding dynamic audio profile without valid format");
return;
}
if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) {
FormatVector formats;
formats.push_back(profileToAdd->getFormat());
addProfilesForFormats(audioProfileVector, FormatVector(formats));
return;
}
if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) {
setSampleRatesForAudioProfiles(
audioProfileVector, profileToAdd->getSampleRates(), profileToAdd->getFormat());
return;
}
if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) {
setChannelsForAudioProfiles(
audioProfileVector, profileToAdd->getChannels(), profileToAdd->getFormat());
return;
}
// Go through the list of profile to avoid duplicates
for (size_t profileIndex = 0; profileIndex < audioProfileVector.size(); profileIndex++) {
const sp<AudioProfile> &profile = audioProfileVector.at(profileIndex);
if (profile->isValid() && profile == profileToAdd) {
// Nothing to do
return;
}
}
profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal
addAudioProfileAndSort(audioProfileVector, profileToAdd);
}
void appendAudioProfiles(AudioProfileVector &audioProfileVector,
const AudioProfileVector &audioProfileVectorToAppend)
{
audioProfileVector.insert(audioProfileVector.end(),
audioProfileVectorToAppend.begin(),
audioProfileVectorToAppend.end());
}
status_t checkExact(const sp<AudioProfile> &audioProfile,
uint32_t samplingRate,
audio_channel_mask_t channelMask,
audio_format_t format)
{
if (audio_formats_match(format, audioProfile->getFormat()) &&
audioProfile->supportsChannels(channelMask) &&
@ -173,60 +306,16 @@ status_t checkCompatibleChannelMask(const sp<AudioProfile> &audioProfile,
return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
}
ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
{
ssize_t index = size();
push_back(profile);
// we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry.
std::sort(begin(), end(),
[](const sp<AudioProfile> & a, const sp<AudioProfile> & b)
{
return AudioPort::compareFormats(a->getFormat(), b->getFormat()) < 0;
});
return index;
}
ssize_t AudioProfileVector::addProfileFromHal(const sp<AudioProfile> &profileToAdd)
status_t checkExactProfile(const AudioProfileVector& audioProfileVector,
const uint32_t samplingRate,
audio_channel_mask_t channelMask,
audio_format_t format)
{
// Check valid profile to add:
if (!profileToAdd->hasValidFormat()) {
return -1;
}
if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) {
FormatVector formats;
formats.push_back(profileToAdd->getFormat());
setFormats(FormatVector(formats));
return 0;
}
if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) {
setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat());
return 0;
}
if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) {
setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat());
return 0;
}
// Go through the list of profile to avoid duplicates
for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) {
const sp<AudioProfile> &profile = at(profileIndex);
if (profile->isValid() && profile == profileToAdd) {
// Nothing to do
return profileIndex;
}
}
profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal
return add(profileToAdd);
}
status_t AudioProfileVector::checkExactProfile(const uint32_t samplingRate,
audio_channel_mask_t channelMask,
audio_format_t format) const
{
if (empty()) {
if (audioProfileVector.empty()) {
return NO_ERROR;
}
for (const auto& profile : *this) {
for (const auto& profile : audioProfileVector) {
if (checkExact(profile, samplingRate, channelMask, format) == NO_ERROR) {
return NO_ERROR;
}
@ -234,13 +323,14 @@ status_t AudioProfileVector::checkExactProfile(const uint32_t samplingRate,
return BAD_VALUE;
}
status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate,
audio_channel_mask_t &channelMask,
audio_format_t &format,
audio_port_type_t portType,
audio_port_role_t portRole) const
status_t checkCompatibleProfile(const AudioProfileVector &audioProfileVector,
uint32_t &samplingRate,
audio_channel_mask_t &channelMask,
audio_format_t &format,
audio_port_type_t portType,
audio_port_role_t portRole)
{
if (empty()) {
if (audioProfileVector.empty()) {
return NO_ERROR;
}
@ -249,8 +339,8 @@ status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate,
&& audio_is_linear_pcm(format);
// iterate from best format to worst format (reverse order)
for (ssize_t i = size() - 1; i >= 0 ; --i) {
const sp<AudioProfile> profile = at(i);
for (ssize_t i = audioProfileVector.size() - 1; i >= 0 ; --i) {
const sp<AudioProfile> profile = audioProfileVector.at(i);
audio_format_t formatToCompare = profile->getFormat();
if (formatToCompare == format ||
(checkInexact
@ -306,23 +396,25 @@ std::vector<typename T::value_type> intersectAndOrder(
return result;
}
status_t AudioProfileVector::findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles,
const std::vector<audio_format_t>& preferredFormats,
const std::vector<audio_channel_mask_t>& preferredOutputChannels,
bool preferHigherSamplingRates,
audio_config_base *bestOutputConfig) const
status_t findBestMatchingOutputConfig(
const AudioProfileVector &audioProfileVector,
const AudioProfileVector &outputProfileVector,
const std::vector<audio_format_t> &preferredFormatVector, // order: most pref -> least pref
const std::vector<audio_channel_mask_t> &preferredOutputChannelVector,
bool preferHigherSamplingRates,
audio_config_base &bestOutputConfig)
{
auto formats = intersectFilterAndOrder(getSupportedFormats(),
outputProfiles.getSupportedFormats(), preferredFormats);
auto formats = intersectFilterAndOrder(audioProfileVector.getSupportedFormats(),
outputProfileVector.getSupportedFormats(), preferredFormatVector);
// Pick the best compatible profile.
for (const auto& f : formats) {
sp<AudioProfile> inputProfile = getFirstValidProfileFor(f);
sp<AudioProfile> outputProfile = outputProfiles.getFirstValidProfileFor(f);
sp<AudioProfile> inputProfile = audioProfileVector.getFirstValidProfileFor(f);
sp<AudioProfile> outputProfile = outputProfileVector.getFirstValidProfileFor(f);
if (inputProfile == nullptr || outputProfile == nullptr) {
continue;
}
auto channels = intersectFilterAndOrder(asOutMask(inputProfile->getChannels()),
outputProfile->getChannels(), preferredOutputChannels);
outputProfile->getChannels(), preferredOutputChannelVector);
if (channels.empty()) {
continue;
}
@ -336,77 +428,12 @@ status_t AudioProfileVector::findBestMatchingOutputConfig(const AudioProfileVect
}
ALOGD("%s() found channel mask %#x and sample rate %d for format %#x.",
__func__, *channels.begin(), *sampleRates.begin(), f);
bestOutputConfig->format = f;
bestOutputConfig->sample_rate = *sampleRates.begin();
bestOutputConfig->channel_mask = *channels.begin();
bestOutputConfig.format = f;
bestOutputConfig.sample_rate = *sampleRates.begin();
bestOutputConfig.channel_mask = *channels.begin();
return NO_ERROR;
}
return BAD_VALUE;
}
void AudioProfileVector::setFormats(const FormatVector &formats)
{
// Only allow to change the format of dynamic profile
sp<AudioProfile> dynamicFormatProfile = getProfileFor(gDynamicFormat);
if (dynamicFormatProfile == 0) {
return;
}
for (const auto &format : formats) {
sp<AudioProfile> profile = new AudioProfile(format,
dynamicFormatProfile->getChannels(),
dynamicFormatProfile->getSampleRates());
profile->setDynamicFormat(true);
profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels());
profile->setDynamicRate(dynamicFormatProfile->isDynamicRate());
add(profile);
}
}
sp<AudioProfile> AudioProfileVector::getProfileFor(audio_format_t format) const
{
for (const auto &profile : *this) {
if (profile->getFormat() == format) {
return profile;
}
}
return nullptr;
}
void AudioProfileVector::setSampleRatesFor(
const SampleRateSet &sampleRates, audio_format_t format)
{
for (const auto &profile : *this) {
if (profile->getFormat() == format && profile->isDynamicRate()) {
if (profile->hasValidRates()) {
// Need to create a new profile with same format
sp<AudioProfile> profileToAdd = new AudioProfile(format, profile->getChannels(),
sampleRates);
profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
add(profileToAdd);
} else {
profile->setSampleRates(sampleRates);
}
return;
}
}
}
void AudioProfileVector::setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format)
{
for (const auto &profile : *this) {
if (profile->getFormat() == format && profile->isDynamicChannels()) {
if (profile->hasValidChannels()) {
// Need to create a new profile with same format
sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMasks,
profile->getSampleRates());
profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
add(profileToAdd);
} else {
profile->setChannels(channelMasks);
}
return;
}
}
}
} // namespace android

@ -36,7 +36,8 @@ void AudioRoute::dump(String8 *dst, int spaces) const
dst->append("\n");
}
bool AudioRoute::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const
bool AudioRoute::supportsPatch(const sp<PolicyAudioPort> &srcPort,
const sp<PolicyAudioPort> &dstPort) const
{
if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
return false;

@ -33,15 +33,9 @@ DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const std::string &tagN
DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
const std::string &tagName) :
AudioPort("", AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE),
mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
DeviceDescriptorBase(type), mTagName(tagName), mEncodedFormats(encodedFormats)
{
mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
if (audio_is_remote_submix_device(type)) {
mAddress = String8("0");
}
/* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
* FIXME: APM should know the version of the HAL and don't add the formats for V5.0.
* For now, the workaround to remove AC3 and IEC61937 support on HDMI is to declare
@ -53,20 +47,15 @@ DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &enc
}
}
audio_port_handle_t DeviceDescriptor::getId() const
{
return mId;
}
void DeviceDescriptor::attach(const sp<HwModule>& module)
{
AudioPort::attach(module);
PolicyAudioPort::attach(module);
mId = getNextUniqueId();
}
void DeviceDescriptor::detach() {
mId = AUDIO_PORT_HANDLE_NONE;
AudioPort::detach();
PolicyAudioPort::detach();
}
template<typename T>
@ -117,6 +106,62 @@ bool DeviceDescriptor::supportsFormat(audio_format_t format)
return false;
}
status_t DeviceDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
audio_port_config *backupConfig)
{
struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
status_t status = NO_ERROR;
toAudioPortConfig(&localBackupConfig);
if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
AudioPortConfig::applyAudioPortConfig(config, backupConfig);
applyPolicyAudioPortConfig(config);
}
if (backupConfig != NULL) {
*backupConfig = localBackupConfig;
}
return status;
}
void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
DeviceDescriptorBase::toAudioPortConfig(dstConfig, srcConfig);
toPolicyAudioPortConfig(dstConfig, srcConfig);
dstConfig->ext.device.hw_module = getModuleHandle();
}
void DeviceDescriptor::toAudioPort(struct audio_port *port) const
{
ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceType);
DeviceDescriptorBase::toAudioPort(port);
port->ext.device.hw_module = getModuleHandle();
}
void DeviceDescriptor::importAudioPortAndPickAudioProfile(
const sp<PolicyAudioPort>& policyPort, bool force) {
if (!force && !policyPort->asAudioPort()->hasDynamicAudioProfile()) {
return;
}
AudioPort::importAudioPort(policyPort->asAudioPort());
policyPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
}
void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const
{
String8 extraInfo;
if (!mTagName.empty()) {
extraInfo.appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.c_str());
}
std::string descBaseDumpStr;
DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, index, extraInfo.string(), verbose);
dst->append(descBaseDumpStr.c_str());
}
void DeviceVector::refreshTypes()
{
mDeviceTypes = AUDIO_DEVICE_NONE;
@ -218,11 +263,11 @@ sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8
// If format is specified, match it and ignore address
// Otherwise if address is specified match it
// Otherwise always match
if (((address == "" || itemAt(i)->address() == address) &&
if (((address == "" || (itemAt(i)->address().compare(address.c_str()) == 0)) &&
format == AUDIO_FORMAT_DEFAULT) ||
(itemAt(i)->supportsFormat(format) && format != AUDIO_FORMAT_DEFAULT)) {
device = itemAt(i);
if (itemAt(i)->address() == address) {
if (itemAt(i)->address().compare(address.c_str()) == 0) {
break;
}
}
@ -315,86 +360,6 @@ void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbo
}
}
void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
dstConfig->config_mask = AUDIO_PORT_CONFIG_GAIN;
if (mSamplingRate != 0) {
dstConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
}
if (mChannelMask != AUDIO_CHANNEL_NONE) {
dstConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
}
if (mFormat != AUDIO_FORMAT_INVALID) {
dstConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
}
if (srcConfig != NULL) {
dstConfig->config_mask |= srcConfig->config_mask;
}
AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
dstConfig->id = mId;
dstConfig->role = audio_is_output_device(mDeviceType) ?
AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
dstConfig->ext.device.type = mDeviceType;
//TODO Understand why this test is necessary. i.e. why at boot time does it crash
// without the test?
// This has been demonstrated to NOT be true (at start up)
// ALOG_ASSERT(mModule != NULL);
dstConfig->ext.device.hw_module = getModuleHandle();
(void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.string());
}
void DeviceDescriptor::toAudioPort(struct audio_port *port) const
{
ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceType);
AudioPort::toAudioPort(port);
port->id = mId;
toAudioPortConfig(&port->active_config);
port->ext.device.type = mDeviceType;
port->ext.device.hw_module = getModuleHandle();
(void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.string());
}
void DeviceDescriptor::importAudioPort(const sp<AudioPort>& port, bool force) {
if (!force && !port->hasDynamicAudioProfile()) {
return;
}
AudioPort::importAudioPort(port);
port->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
}
void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const
{
dst->appendFormat("%*sDevice %d:\n", spaces, "", index + 1);
if (mId != 0) {
dst->appendFormat("%*s- id: %2d\n", spaces, "", mId);
}
if (!mTagName.empty()) {
dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.c_str());
}
dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str());
if (mAddress.size() != 0) {
dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string());
}
std::string portStr;
AudioPort::dump(&portStr, spaces, verbose);
dst->append(portStr.c_str());
}
std::string DeviceDescriptor::toString() const
{
std::stringstream sstream;
sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
return sstream.str();
}
std::string DeviceVector::toString() const
{
if (isEmpty()) {
@ -443,13 +408,4 @@ DeviceVector DeviceVector::filterForEngine() const
return filteredDevices;
}
void DeviceDescriptor::log() const
{
ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceType,
::android::toString(mDeviceType).c_str(),
mAddress.string());
AudioPort::log(" ");
}
} // namespace android

@ -50,7 +50,7 @@ status_t HwModule::addOutputProfile(const std::string& name, const audio_config_
config->sample_rate));
sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
devDesc->setAddress(address);
devDesc->setAddress(address.string());
addDynamicDevice(devDesc);
// Reciprocally attach the device to the module
devDesc->attach(this);
@ -118,7 +118,7 @@ status_t HwModule::addInputProfile(const std::string& name, const audio_config_t
config->sample_rate));
sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
devDesc->setAddress(address);
devDesc->setAddress(address.string());
addDynamicDevice(devDesc);
// Reciprocally attach the device to the module
devDesc->attach(this);
@ -156,7 +156,7 @@ void HwModule::setDeclaredDevices(const DeviceVector &devices)
sp<DeviceDescriptor> HwModule::getRouteSinkDevice(const sp<AudioRoute> &route) const
{
sp<DeviceDescriptor> sinkDevice = 0;
if (route->getSink()->getType() == AUDIO_PORT_TYPE_DEVICE) {
if (route->getSink()->asAudioPort()->getType() == AUDIO_PORT_TYPE_DEVICE) {
sinkDevice = mDeclaredDevices.getDeviceFromTagName(route->getSink()->getTagName());
}
return sinkDevice;
@ -166,7 +166,7 @@ DeviceVector HwModule::getRouteSourceDevices(const sp<AudioRoute> &route) const
{
DeviceVector sourceDevices;
for (const auto& source : route->getSources()) {
if (source->getType() == AUDIO_PORT_TYPE_DEVICE) {
if (source->asAudioPort()->getType() == AUDIO_PORT_TYPE_DEVICE) {
sourceDevices.add(mDeclaredDevices.getDeviceFromTagName(source->getTagName()));
}
}
@ -186,7 +186,7 @@ void HwModule::refreshSupportedDevices()
for (const auto& stream : mInputProfiles) {
DeviceVector sourceDevices;
for (const auto& route : stream->getRoutes()) {
sp<AudioPort> sink = route->getSink();
sp<PolicyAudioPort> sink = route->getSink();
if (sink == 0 || stream != sink) {
ALOGE("%s: Invalid route attached to input stream", __FUNCTION__);
continue;
@ -207,7 +207,7 @@ void HwModule::refreshSupportedDevices()
for (const auto& stream : mOutputProfiles) {
DeviceVector sinkDevices;
for (const auto& route : stream->getRoutes()) {
sp<AudioPort> source = route->getSources().findByTagName(stream->getTagName());
sp<PolicyAudioPort> source = findByTagName(route->getSources(), stream->getTagName());
if (source == 0 || stream != source) {
ALOGE("%s: Invalid route attached to output stream", __FUNCTION__);
continue;
@ -229,7 +229,8 @@ void HwModule::setHandle(audio_module_handle_t handle) {
mHandle = handle;
}
bool HwModule::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const {
bool HwModule::supportsPatch(const sp<PolicyAudioPort> &srcPort,
const sp<PolicyAudioPort> &dstPort) const {
for (const auto &route : mRoutes) {
if (route->supportsPatch(srcPort, dstPort)) {
return true;
@ -259,7 +260,7 @@ void HwModule::dump(String8 *dst) const
}
mDeclaredDevices.dump(dst, String8("Declared"), 2, true);
mDynamicDevices.dump(dst, String8("Dynamic"), 2, true);
mRoutes.dump(dst, 2);
dumpAudioRouteVector(mRoutes, dst, 2);
}
sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
@ -334,7 +335,7 @@ sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices
}
if (allowToCreate) {
moduleDevice->attach(hwModule);
moduleDevice->setAddress(devAddress);
moduleDevice->setAddress(devAddress.string());
moduleDevice->setName(name);
}
return moduleDevice;
@ -361,7 +362,7 @@ sp<DeviceDescriptor> HwModuleCollection::createDevice(const audio_devices_t type
}
sp<DeviceDescriptor> device = new DeviceDescriptor(type, name);
device->setName(name);
device->setAddress(String8(address));
device->setAddress(address);
device->setEncodedFormat(encodedFormat);
// Add the device to the list of dynamic devices
@ -381,7 +382,7 @@ sp<DeviceDescriptor> HwModuleCollection::createDevice(const audio_devices_t type
// @todo quid of audio profile? import the profile from device of the same type?
const auto &isoTypeDeviceForProfile =
profile->getSupportedDevices().getDevice(type, String8(), AUDIO_FORMAT_DEFAULT);
device->importAudioPort(isoTypeDeviceForProfile, true /* force */);
device->importAudioPortAndPickAudioProfile(isoTypeDeviceForProfile, true /* force */);
ALOGV("%s: adding device %s to profile %s", __FUNCTION__,
device->toString().c_str(), profile->getTagName().c_str());

@ -14,10 +14,10 @@
* limitations under the License.
*/
#define LOG_TAG "APM::AudioPort"
#define LOG_TAG "APM::PolicyAudioPort"
//#define LOG_NDEBUG 0
#include "TypeConverter.h"
#include "AudioPort.h"
#include "PolicyAudioPort.h"
#include "HwModule.h"
#include <policy.h>
@ -27,81 +27,61 @@
namespace android {
// --- AudioPort class implementation
void AudioPort::attach(const sp<HwModule>& module)
// --- PolicyAudioPort class implementation
void PolicyAudioPort::attach(const sp<HwModule>& module)
{
ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.c_str());
ALOGV("%s: attaching module %s to port %s",
__FUNCTION__, getModuleName(), asAudioPort()->getName().c_str());
mModule = module;
}
void AudioPort::detach()
void PolicyAudioPort::detach()
{
mModule = nullptr;
}
// Note that is a different namespace than AudioFlinger unique IDs
audio_port_handle_t AudioPort::getNextUniqueId()
audio_port_handle_t PolicyAudioPort::getNextUniqueId()
{
return getNextHandle();
}
audio_module_handle_t AudioPort::getModuleHandle() const
audio_module_handle_t PolicyAudioPort::getModuleHandle() const
{
return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
}
uint32_t AudioPort::getModuleVersionMajor() const
uint32_t PolicyAudioPort::getModuleVersionMajor() const
{
return mModule != 0 ? mModule->getHalVersionMajor() : 0;
}
const char *AudioPort::getModuleName() const
const char *PolicyAudioPort::getModuleName() const
{
return mModule != 0 ? mModule->getName() : "invalid module";
}
void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
{
for (const auto& profileToImport : port->mProfiles) {
if (profileToImport->isValid()) {
// Import only valid port, i.e. valid format, non empty rates and channels masks
bool hasSameProfile = false;
for (const auto& profile : mProfiles) {
if (*profile == *profileToImport) {
// never import a profile twice
hasSameProfile = true;
break;
}
}
if (hasSameProfile) { // never import a same profile twice
continue;
}
addAudioProfile(profileToImport);
}
}
}
status_t AudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
status_t PolicyAudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
{
status_t status = NO_ERROR;
auto config_mask = config->config_mask;
if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
status = checkGain(&config->gain, config->gain.index);
status = asAudioPort()->checkGain(&config->gain, config->gain.index);
if (status != NO_ERROR) {
return status;
}
}
if (config_mask != 0) {
// TODO should we check sample_rate / channel_mask / format separately?
status = mProfiles.checkExactProfile(config->sample_rate,
config->channel_mask,
config->format);
status = checkExactProfile(asAudioPort()->getAudioProfiles(), config->sample_rate,
config->channel_mask, config->format);
}
return status;
}
void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateSet &samplingRates) const
void PolicyAudioPort::pickSamplingRate(uint32_t &pickedRate,
const SampleRateSet &samplingRates) const
{
pickedRate = 0;
// For direct outputs, pick minimum sampling rate: this helps ensuring that the
@ -121,7 +101,7 @@ void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateSet &sampl
// For mixed output and inputs, use max mixer sampling rates. Do not
// limit sampling rate otherwise
// For inputs, also see checkCompatibleSamplingRate().
if (mType != AUDIO_PORT_TYPE_MIX) {
if (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) {
maxRate = UINT_MAX;
}
// TODO: should mSamplingRates[] be ordered in terms of our preference
@ -135,8 +115,8 @@ void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateSet &sampl
}
}
void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
const ChannelMaskSet &channelMasks) const
void PolicyAudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
const ChannelMaskSet &channelMasks) const
{
pickedChannelMask = AUDIO_CHANNEL_NONE;
// For direct outputs, pick minimum channel count: this helps ensuring that the
@ -146,7 +126,7 @@ void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
uint32_t channelCount = UINT_MAX;
for (const auto channelMask : channelMasks) {
uint32_t cnlCount;
if (useInputChannelMask()) {
if (asAudioPort()->useInputChannelMask()) {
cnlCount = audio_channel_count_from_in_mask(channelMask);
} else {
cnlCount = audio_channel_count_from_out_mask(channelMask);
@ -162,12 +142,12 @@ void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
// For mixed output and inputs, use max mixer channel count. Do not
// limit channel count otherwise
if (mType != AUDIO_PORT_TYPE_MIX) {
if (asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) {
maxCount = UINT_MAX;
}
for (const auto channelMask : channelMasks) {
uint32_t cnlCount;
if (useInputChannelMask()) {
if (asAudioPort()->useInputChannelMask()) {
cnlCount = audio_channel_count_from_in_mask(channelMask);
} else {
cnlCount = audio_channel_count_from_out_mask(channelMask);
@ -181,7 +161,7 @@ void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
}
/* format in order of increasing preference */
const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
const audio_format_t PolicyAudioPort::sPcmFormatCompareTable[] = {
AUDIO_FORMAT_DEFAULT,
AUDIO_FORMAT_PCM_16_BIT,
AUDIO_FORMAT_PCM_8_24_BIT,
@ -190,7 +170,7 @@ const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
AUDIO_FORMAT_PCM_FLOAT,
};
int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
int PolicyAudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
{
// NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
// compressed format and better than any PCM format. This is by design of pickFormat()
@ -220,7 +200,7 @@ int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
return index1 - index2;
}
uint32_t AudioPort::formatDistance(audio_format_t format1, audio_format_t format2)
uint32_t PolicyAudioPort::formatDistance(audio_format_t format1, audio_format_t format2)
{
if (format1 == format2) {
return 0;
@ -234,43 +214,44 @@ uint32_t AudioPort::formatDistance(audio_format_t format1, audio_format_t format
return abs(diffBytes);
}
bool AudioPort::isBetterFormatMatch(audio_format_t newFormat,
audio_format_t currentFormat,
audio_format_t targetFormat)
bool PolicyAudioPort::isBetterFormatMatch(audio_format_t newFormat,
audio_format_t currentFormat,
audio_format_t targetFormat)
{
return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat);
}
void AudioPort::pickAudioProfile(uint32_t &samplingRate,
audio_channel_mask_t &channelMask,
audio_format_t &format) const
void PolicyAudioPort::pickAudioProfile(uint32_t &samplingRate,
audio_channel_mask_t &channelMask,
audio_format_t &format) const
{
format = AUDIO_FORMAT_DEFAULT;
samplingRate = 0;
channelMask = AUDIO_CHANNEL_NONE;
// special case for uninitialized dynamic profile
if (!mProfiles.hasValidProfile()) {
if (!asAudioPort()->hasValidAudioProfile()) {
return;
}
audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
// For mixed output and inputs, use best mixer output format.
// Do not limit format otherwise
if ((mType != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
if ((asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
bestFormat = AUDIO_FORMAT_INVALID;
}
for (size_t i = 0; i < mProfiles.size(); i ++) {
if (!mProfiles[i]->isValid()) {
const AudioProfileVector& audioProfiles = asAudioPort()->getAudioProfiles();
for (size_t i = 0; i < audioProfiles.size(); i ++) {
if (!audioProfiles[i]->isValid()) {
continue;
}
audio_format_t formatToCompare = mProfiles[i]->getFormat();
audio_format_t formatToCompare = audioProfiles[i]->getFormat();
if ((compareFormats(formatToCompare, format) > 0) &&
(compareFormats(formatToCompare, bestFormat) <= 0)) {
uint32_t pickedSamplingRate = 0;
audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
pickChannelMask(pickedChannelMask, mProfiles[i]->getChannels());
pickSamplingRate(pickedSamplingRate, mProfiles[i]->getSampleRates());
pickChannelMask(pickedChannelMask, audioProfiles[i]->getChannels());
pickSamplingRate(pickedSamplingRate, audioProfiles[i]->getSampleRates());
if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
&& pickedSamplingRate != 0) {
@ -281,120 +262,33 @@ void AudioPort::pickAudioProfile(uint32_t &samplingRate,
}
}
}
ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.c_str(),
samplingRate, channelMask, format);
}
void AudioPort::log(const char* indent) const
{
ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__,
asAudioPort()->getName().c_str(), samplingRate, channelMask, format);
}
// --- AudioPortConfig class implementation
// --- PolicyAudioPortConfig class implementation
status_t AudioPortConfig::applyAudioPortConfig(const struct audio_port_config *config,
struct audio_port_config *backupConfig)
status_t PolicyAudioPortConfig::validationBeforeApplyConfig(
const struct audio_port_config *config) const
{
struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
status_t status = NO_ERROR;
toAudioPortConfig(&localBackupConfig);
sp<AudioPort> audioport = getAudioPort();
if (audioport == 0) {
status = NO_INIT;
goto exit;
}
status = audioport->checkExactAudioProfile(config);
if (status != NO_ERROR) {
goto exit;
}
if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
mSamplingRate = config->sample_rate;
}
if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
mChannelMask = config->channel_mask;
}
if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
mFormat = config->format;
}
if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
mGain = config->gain;
}
if (config->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
mFlags = config->flags;
}
exit:
if (status != NO_ERROR) {
applyAudioPortConfig(&localBackupConfig);
}
if (backupConfig != NULL) {
*backupConfig = localBackupConfig;
}
return status;
sp<PolicyAudioPort> policyAudioPort = getPolicyAudioPort();
return policyAudioPort ? policyAudioPort->checkExactAudioProfile(config) : NO_INIT;
}
namespace {
template<typename T>
void updateField(
const T& portConfigField, T audio_port_config::*port_config_field,
struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig,
unsigned int configMask, T defaultValue)
void PolicyAudioPortConfig::toPolicyAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
if (dstConfig->config_mask & configMask) {
if ((srcConfig != nullptr) && (srcConfig->config_mask & configMask)) {
dstConfig->*port_config_field = srcConfig->*port_config_field;
if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
if ((srcConfig != nullptr) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FLAGS)) {
dstConfig->flags = srcConfig->flags;
} else {
dstConfig->*port_config_field = portConfigField;
dstConfig->flags = mFlags;
}
} else {
dstConfig->*port_config_field = defaultValue;
dstConfig->flags = { AUDIO_INPUT_FLAG_NONE };
}
}
} // namespace
void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
updateField(mSamplingRate, &audio_port_config::sample_rate,
dstConfig, srcConfig, AUDIO_PORT_CONFIG_SAMPLE_RATE, 0u);
updateField(mChannelMask, &audio_port_config::channel_mask,
dstConfig, srcConfig, AUDIO_PORT_CONFIG_CHANNEL_MASK,
(audio_channel_mask_t)AUDIO_CHANNEL_NONE);
updateField(mFormat, &audio_port_config::format,
dstConfig, srcConfig, AUDIO_PORT_CONFIG_FORMAT, AUDIO_FORMAT_INVALID);
sp<AudioPort> audioport = getAudioPort();
if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
dstConfig->gain = mGain;
if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
&& audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
dstConfig->gain = srcConfig->gain;
}
} else {
dstConfig->gain.index = -1;
}
if (dstConfig->gain.index != -1) {
dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
} else {
dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
}
updateField(mFlags, &audio_port_config::flags,
dstConfig, srcConfig, AUDIO_PORT_CONFIG_FLAGS, { AUDIO_INPUT_FLAG_NONE });
}
bool AudioPortConfig::hasGainController(bool canUseForVolume) const
{
sp<AudioPort> audioport = getAudioPort();
if (audioport == nullptr) {
return false;
}
return canUseForVolume ? audioport->getGains().canUseForVolume()
: audioport->getGains().size() > 0;
}
} // namespace android

@ -440,6 +440,9 @@ Return<MixPortTraits::Element> MixPortTraits::deserialize(const xmlNode *child,
if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
}
// The audio profiles are in order of listed in audio policy configuration file.
// Sort audio profiles accroding to the format.
sortAudioProfiles(profiles);
mixPort->setAudioProfiles(profiles);
std::string flags = getXmlAttribute(child, Attributes::flags);
@ -513,7 +516,7 @@ Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *c
std::string address = getXmlAttribute(cur, Attributes::address);
if (!address.empty()) {
ALOGV("%s: address=%s for %s", __func__, address.c_str(), name.c_str());
deviceDesc->setAddress(String8(address.c_str()));
deviceDesc->setAddress(address);
}
AudioProfileTraits::Collection profiles;
@ -524,6 +527,9 @@ Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *c
if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
}
// The audio profiles are in order of listed in audio policy configuration file.
// Sort audio profiles accroding to the format.
sortAudioProfiles(profiles);
deviceDesc->setAudioProfiles(profiles);
// Deserialize AudioGain children
@ -532,7 +538,7 @@ Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *c
return Status::fromStatusT(status);
}
ALOGV("%s: adding device tag %s type %08x address %s", __func__,
deviceDesc->getName().c_str(), type, deviceDesc->address().string());
deviceDesc->getName().c_str(), type, deviceDesc->address().c_str());
return deviceDesc;
}
@ -555,7 +561,7 @@ Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSer
return Status::fromStatusT(BAD_VALUE);
}
// Convert Sink name to port pointer
sp<AudioPort> sink = ctx->findPortByTagName(sinkAttr);
sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
if (sink == NULL) {
ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
return Status::fromStatusT(BAD_VALUE);
@ -568,13 +574,13 @@ Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSer
return Status::fromStatusT(BAD_VALUE);
}
// Tokenize and Convert Sources name to port pointer
AudioPortVector sources;
PolicyAudioPortVector sources;
std::unique_ptr<char[]> sourcesLiteral{strndup(
sourcesAttr.c_str(), strlen(sourcesAttr.c_str()))};
char *devTag = strtok(sourcesLiteral.get(), ",");
while (devTag != NULL) {
if (strlen(devTag) != 0) {
sp<AudioPort> source = ctx->findPortByTagName(devTag);
sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
if (source == NULL) {
ALOGE("%s: no source found with name=%s", __func__, devTag);
return Status::fromStatusT(BAD_VALUE);
@ -586,7 +592,7 @@ Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSer
sink->addRoute(route);
for (size_t i = 0; i < sources.size(); i++) {
sp<AudioPort> source = sources.itemAt(i);
sp<PolicyAudioPort> source = sources.itemAt(i);
source->addRoute(route);
}
route->setSources(sources);

@ -16,7 +16,7 @@
#pragma once
#include <AudioPort.h>
#include <PolicyAudioPort.h>
#include <AudioPatch.h>
#include <IOProfile.h>
#include <DeviceDescriptor.h>

@ -259,7 +259,7 @@ status_t ParameterManagerWrapper::setDeviceConnectionState(const sp<DeviceDescri
std::string criterionName = audio_is_output_device(devDesc->type()) ?
gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
ALOGV("%s: device with address %s %s", __FUNCTION__, devDesc->address().string(),
ALOGV("%s: device with address %s %s", __FUNCTION__, devDesc->address().c_str(),
state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
ISelectionCriterionInterface *criterion =
getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
@ -271,7 +271,7 @@ status_t ParameterManagerWrapper::setDeviceConnectionState(const sp<DeviceDescri
auto criterionType = criterion->getCriterionType();
int deviceAddressId;
if (not criterionType->getNumericalValue(devDesc->address().string(), deviceAddressId)) {
if (not criterionType->getNumericalValue(devDesc->address().c_str(), deviceAddressId)) {
ALOGW("%s: unknown device address reported (%s)", __FUNCTION__, devDesc->address().c_str());
return BAD_TYPE;
}

@ -16,7 +16,7 @@
#pragma once
#include <AudioPort.h>
#include <PolicyAudioPort.h>
#include <HwModule.h>
#include <DeviceDescriptor.h>
#include <system/audio.h>

@ -27,7 +27,7 @@
#include "Engine.h"
#include <android-base/macros.h>
#include <AudioPolicyManagerObserver.h>
#include <AudioPort.h>
#include <PolicyAudioPort.h>
#include <IOProfile.h>
#include <AudioIODescriptorInterface.h>
#include <policy.h>
@ -212,7 +212,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
((availPrimaryInputDevices.getDevice(
txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
(primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) {
(primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
availableOutputDevices = availPrimaryOutputDevices;
}
}

@ -112,7 +112,7 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
void AudioPolicyManager::broadcastDeviceConnectionState(const sp<DeviceDescriptor> &device,
audio_policy_dev_state_t state)
{
AudioParameter param(device->address());
AudioParameter param(String8(device->address().c_str()));
const String8 key(state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE ?
AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect);
param.addInt(key, device->type());
@ -1109,7 +1109,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
.channel_mask = config->channel_mask,
.format = config->format,
};
*portId = AudioPort::getNextUniqueId();
*portId = PolicyAudioPort::getNextUniqueId();
sp<TrackClientDescriptor> clientDesc =
new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
@ -1360,19 +1360,19 @@ status_t AudioPolicyManager::getBestMsdAudioProfileFor(const sp<DeviceDescriptor
// Each IOProfile represents a MixPort from audio_policy_configuration.xml
for (const auto &inProfile : inputProfiles) {
if (hwAvSync == ((inProfile->getFlags() & AUDIO_INPUT_FLAG_HW_AV_SYNC) != 0)) {
msdProfiles.appendProfiles(inProfile->getAudioProfiles());
appendAudioProfiles(msdProfiles, inProfile->getAudioProfiles());
}
}
AudioProfileVector deviceProfiles;
for (const auto &outProfile : outputProfiles) {
if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0)) {
deviceProfiles.appendProfiles(outProfile->getAudioProfiles());
appendAudioProfiles(deviceProfiles, outProfile->getAudioProfiles());
}
}
struct audio_config_base bestSinkConfig;
status_t result = msdProfiles.findBestMatchingOutputConfig(deviceProfiles,
status_t result = findBestMatchingOutputConfig(msdProfiles, deviceProfiles,
compressedFormatsOrder, surroundChannelMasksOrder, true /*preferHigherSamplingRates*/,
&bestSinkConfig);
bestSinkConfig);
if (result != NO_ERROR) {
ALOGD("%s() no matching profiles found for device: %s, hwAvSync: %d",
__func__, outputDevice->toString().c_str(), hwAvSync);
@ -1563,8 +1563,8 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
// format match
if (format != AUDIO_FORMAT_INVALID) {
currentMatchCriteria[6] =
AudioPort::kFormatDistanceMax -
AudioPort::formatDistance(format, outputDesc->getFormat());
PolicyAudioPort::kFormatDistanceMax -
PolicyAudioPort::formatDistance(format, outputDesc->getFormat());
}
// primary output match
@ -2088,7 +2088,7 @@ exit:
isSoundTrigger = attributes.source == AUDIO_SOURCE_HOTWORD &&
mSoundTriggerSessions.indexOfKey(session) >= 0;
*portId = AudioPort::getNextUniqueId();
*portId = PolicyAudioPort::getNextUniqueId();
clientDesc = new RecordClientDescriptor(*portId, riid, uid, session, attributes, *config,
requestedDeviceId, attributes.source, flags,
@ -2431,7 +2431,8 @@ void AudioPolicyManager::checkCloseInputs() {
const sp<AudioInputDescriptor> input = mInputs.valueAt(i);
if (input->clientsList().size() == 0
|| !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())
|| (input->getAudioPort()->getFlags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
|| (input->getPolicyAudioPort()->getFlags()
& AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
inputsToClose.push_back(mInputs.keyAt(i));
} else {
bool close = false;
@ -3857,7 +3858,7 @@ status_t AudioPolicyManager::startAudioSource(const struct audio_port_config *so
return BAD_VALUE;
}
*portId = AudioPort::getNextUniqueId();
*portId = PolicyAudioPort::getNextUniqueId();
struct audio_patch dummyPatch = {};
sp<AudioPatch> patchDesc = new AudioPatch(&dummyPatch, uid);
@ -4137,7 +4138,7 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat
AUDIO_DEVICE_OUT_HDMI);
for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
String8 address = hdmiOutputDevices[i]->address();
String8 address = String8(hdmiOutputDevices[i]->address().c_str());
std::string name = hdmiOutputDevices[i]->getName();
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
@ -4159,7 +4160,7 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat
AUDIO_DEVICE_IN_HDMI);
for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
String8 address = hdmiInputDevices[i]->address();
String8 address = String8(hdmiInputDevices[i]->address().c_str());
std::string name = hdmiInputDevices[i]->getName();
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
@ -4471,7 +4472,7 @@ status_t AudioPolicyManager::initialize() {
// give a valid ID to an attached device once confirmed it is reachable
if (!device->isAttached()) {
device->attach(hwModule);
device->importAudioPort(inProfile, true);
device->importAudioPortAndPickAudioProfile(inProfile, true);
}
}
inputDesc->close();
@ -4502,11 +4503,11 @@ status_t AudioPolicyManager::initialize() {
}
// If microphones address is empty, set it according to device type
for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
if (mAvailableInputDevices[i]->address().isEmpty()) {
if (mAvailableInputDevices[i]->address().empty()) {
if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
mAvailableInputDevices[i]->setAddress(String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS));
mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
} else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
mAvailableInputDevices[i]->setAddress(String8(AUDIO_BACK_MICROPHONE_ADDRESS));
mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
}
}
}
@ -4575,7 +4576,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
SortedVector<audio_io_handle_t>& outputs)
{
audio_devices_t deviceType = device->type();
const String8 &address = device->address();
const String8 &address = String8(device->address().c_str());
sp<SwAudioOutputDescriptor> desc;
if (audio_device_is_digital(deviceType)) {
@ -4627,7 +4628,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
// matching profile: save the sample rates, format and channel masks supported
// by the profile in our device descriptor
if (audio_device_is_digital(deviceType)) {
device->importAudioPort(profile);
device->importAudioPortAndPickAudioProfile(profile);
}
break;
}
@ -4729,7 +4730,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
outputs.add(output);
// Load digital format info only for digital devices
if (audio_device_is_digital(deviceType)) {
device->importAudioPort(profile);
device->importAudioPortAndPickAudioProfile(profile);
}
if (device_distinguishes_on_address(deviceType)) {
@ -4823,7 +4824,7 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
desc = mInputs.valueAt(input_index);
if (desc->mProfile == profile) {
if (audio_device_is_digital(device->type())) {
device->importAudioPort(profile);
device->importAudioPortAndPickAudioProfile(profile);
}
break;
}
@ -4847,7 +4848,7 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
&input);
if (status == NO_ERROR) {
const String8& address = device->address();
const String8& address = String8(device->address().c_str());
if (!address.isEmpty()) {
char *param = audio_device_address_to_parameter(device->type(), address);
mpClientInterface->setParameters(input, String8(param));
@ -4872,7 +4873,7 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
profile_index--;
} else {
if (audio_device_is_digital(device->type())) {
device->importAudioPort(profile);
device->importAudioPortAndPickAudioProfile(profile);
}
ALOGV("checkInputsForDevice(): adding input %d", input);
}
@ -6168,7 +6169,7 @@ void AudioPolicyManager::updateAudioProfiles(const sp<DeviceDescriptor>& devDesc
|| isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
modifySurroundFormats(devDesc, &formats);
}
profiles.setFormats(formats);
addProfilesForFormats(profiles, formats);
}
for (audio_format_t format : profiles.getSupportedFormats()) {
@ -6204,7 +6205,8 @@ void AudioPolicyManager::updateAudioProfiles(const sp<DeviceDescriptor>& devDesc
}
}
}
profiles.addProfileFromHal(new AudioProfile(format, channelMasks, samplingRates));
addDynamicAudioProfileAndSort(
profiles, new AudioProfile(format, channelMasks, samplingRates));
}
}

@ -31,14 +31,14 @@
#include <utils/SortedVector.h>
#include <media/AudioParameter.h>
#include <media/AudioPolicy.h>
#include <media/AudioProfile.h>
#include <media/PatchBuilder.h>
#include "AudioPolicyInterface.h"
#include <AudioPolicyManagerObserver.h>
#include <AudioPolicyConfig.h>
#include <AudioPort.h>
#include <PolicyAudioPort.h>
#include <AudioPatch.h>
#include <AudioProfileVector.h>
#include <DeviceDescriptor.h>
#include <IOProfile.h>
#include <HwModule.h>
@ -646,7 +646,8 @@ protected:
}
String8 getFirstDeviceAddress(const DeviceVector &devices) const
{
return (devices.size() > 0) ? devices.itemAt(0)->address() : String8("");
return (devices.size() > 0) ?
String8(devices.itemAt(0)->address().c_str()) : String8("");
}
uint32_t updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs = 0);

Loading…
Cancel
Save