Make audio port in policy not derive from audio port base

This patch aims to make the structure for libaudiofoundation and policy
stuff simpler, including:
1. Make AudioPortBase as AudioPort in libaudiofoundation. Create
PolicyAudioPort that contains policy related stuff, which is used by
audiopolicy.
2. Make AudioPortConfigBase as AudioPortConfig in libaudiofoundation.
Create PolicyAudioPortConfig that contains policy related stuff.
3. DeviceDescriptor derives from AudioPort, AudioPortConfig, PolicyAudioPort
and PolicyAudioPortConfig. IOProfile derives from AudioPort,
PolicyAudioPort. AudioInputDescriptor/AudioOutputDescriptor derives from
AudioPortConfig, PolicyAudioPortConfig.

Test: atest AudioTrackTest, AudioRecordTest, AudioManagerTest
Test: atest audiopolicy_tests, AudioHostTest
Test: audio smoke test
Bug: 135621476
Change-Id: I40299d95dda3b3fc0ea88b079f2fe38d8f7e5b31
gugelfrei
jiabin 5 years ago
parent 811797a669
commit 4ef934543d

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "AudioPortBase"
#include <algorithm>
@ -22,7 +23,22 @@
namespace android {
void AudioPortBase::toAudioPort(struct audio_port *port) const {
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;
@ -64,7 +80,7 @@ void AudioPortBase::toAudioPort(struct audio_port *port) const {
}
}
void AudioPortBase::dump(std::string *dst, int spaces, bool verbose) const {
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()));
}
@ -84,4 +100,92 @@ void AudioPortBase::dump(std::string *dst, int spaces, bool verbose) const {
}
}
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;
}
}

@ -27,13 +27,13 @@
namespace android {
class AudioPortBase : public virtual RefBase
class AudioPort : public virtual RefBase
{
public:
AudioPortBase(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 ~AudioPortBase() = default;
virtual ~AudioPort() = default;
void setName(const std::string &name) { mName = name; }
const std::string &getName() const { return mName; }
@ -41,8 +41,6 @@ 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; }
@ -57,9 +55,13 @@ public:
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()) {
return BAD_VALUE;
@ -75,6 +77,8 @@ 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;
@ -84,24 +88,31 @@ protected:
};
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 };
};

@ -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

@ -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

@ -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.

@ -33,24 +33,24 @@ namespace android {
class HwModule;
class AudioRoute;
class AudioPort : public AudioPortBase, 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;
void addAudioProfile(const sp<AudioProfile> &profile) {
addAudioProfileAndSort(mProfiles, profile);
}
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;
@ -64,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 mProfiles.hasDynamicProfile(); }
// searches for an exact match
virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
@ -78,7 +74,8 @@ public:
audio_format_t &format) const
{
return checkCompatibleProfile(
mProfiles, samplingRate, channelMask, format, mType, mRole);
asAudioPort()->getAudioProfiles(), samplingRate, channelMask, format,
asAudioPort()->getType(), asAudioPort()->getRole());
}
void pickAudioProfile(uint32_t &samplingRate,
@ -105,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;
@ -124,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 };
};

@ -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;
};

@ -26,7 +26,8 @@
namespace android {
class DeviceDescriptor : public AudioPort, public AudioPortConfig
class DeviceDescriptor : public AudioPort, public AudioPortConfig,
public PolicyAudioPort, public PolicyAudioPortConfig
{
public:
// Note that empty name refers by convention to a generic device.
@ -36,6 +37,10 @@ public:
virtual ~DeviceDescriptor() {}
virtual void addAudioProfile(const sp<AudioProfile> &profile) {
addAudioProfileAndSort(mProfiles, profile);
}
virtual const std::string getTagName() const { return mTagName; }
audio_devices_t type() const { return mDeviceType; }
@ -56,19 +61,33 @@ 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 sp<AudioPort> getAudioPort() const {
return static_cast<AudioPort*>(const_cast<DeviceDescriptor*>(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;
@ -78,7 +97,6 @@ private:
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;
};

@ -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> >

@ -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;
}

@ -24,9 +24,10 @@
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();
@ -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;

@ -27,80 +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 = checkExactProfile(mProfiles, config->sample_rate,
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
@ -120,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
@ -134,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
@ -145,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);
@ -161,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);
@ -180,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,
@ -189,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()
@ -219,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;
@ -233,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) {
@ -280,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

@ -36,7 +36,7 @@ void sortAudioProfiles(AudioProfileVector &audioProfileVector) {
std::sort(audioProfileVector.begin(), audioProfileVector.end(),
[](const sp<AudioProfile> & a, const sp<AudioProfile> & b)
{
return AudioPort::compareFormats(a->getFormat(), b->getFormat()) < 0;
return PolicyAudioPort::compareFormats(a->getFormat(), b->getFormat()) < 0;
});
}

@ -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;

@ -53,20 +53,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>
@ -315,6 +310,24 @@ void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbo
}
}
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
{
@ -334,8 +347,8 @@ void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
}
AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
toPolicyAudioPortConfig(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;
@ -360,12 +373,13 @@ void DeviceDescriptor::toAudioPort(struct audio_port *port) const
(void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.string());
}
void DeviceDescriptor::importAudioPort(const sp<AudioPort>& port, bool force) {
if (!force && !port->hasDynamicAudioProfile()) {
void DeviceDescriptor::importAudioPortAndPickAudioProfile(
const sp<PolicyAudioPort>& policyPort, bool force) {
if (!force && !policyPort->asAudioPort()->hasDynamicAudioProfile()) {
return;
}
AudioPort::importAudioPort(port);
port->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
AudioPort::importAudioPort(policyPort->asAudioPort());
policyPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
}
void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const

@ -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
@ -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());

@ -561,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);
@ -574,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);
@ -592,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);

@ -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;
}
}

@ -1108,7 +1108,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
.format = config->format,
.channel_mask = config->channel_mask };
*portId = AudioPort::getNextUniqueId();
*portId = PolicyAudioPort::getNextUniqueId();
sp<TrackClientDescriptor> clientDesc =
new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
@ -1562,8 +1562,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
@ -2087,7 +2087,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,
@ -2430,7 +2430,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;
@ -3856,7 +3857,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);
@ -4470,7 +4471,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();
@ -4626,7 +4627,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;
}
@ -4728,7 +4729,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)) {
@ -4822,7 +4823,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;
}
@ -4871,7 +4872,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);
}

Loading…
Cancel
Save