Clear up bit mask usage in audio policy.

This change includes:
1. Use DeviceTypeSet to represent a combination of audio device types.
2. Add helper functions for DeviceTypeSet
3. Stop using audio device type as a bit mask in DeviceVector

Test: atest AudioTrackTest AudioRecordTest AudioPlaybackCaptureTest
Test: atest AudioHostTest AudioServiceHostTest audiopolicy_tests
Test: audio smoke test
Change-Id: If80513b689848bcab6094f70a572f053856afa82
Merged-In: If80513b689848bcab6094f70a572f053856afa82
gugelfrei
jiabin 5 years ago
parent 4ad3d03f61
commit 12dc6b0e9f

@ -9,6 +9,7 @@ cc_library_shared {
vendor_available: true,
srcs: [
"AudioContainers.cpp",
"AudioGain.cpp",
"AudioPort.cpp",
"AudioProfile.cpp",

@ -0,0 +1,86 @@
/*
* 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 <sstream>
#include <string>
#include <media/AudioContainers.h>
namespace android {
const DeviceTypeSet& getAudioDeviceOutAllSet() {
static const DeviceTypeSet audioDeviceOutAllSet = DeviceTypeSet(
std::begin(AUDIO_DEVICE_OUT_ALL_ARRAY),
std::end(AUDIO_DEVICE_OUT_ALL_ARRAY));
return audioDeviceOutAllSet;
}
const DeviceTypeSet& getAudioDeviceOutAllA2dpSet() {
static const DeviceTypeSet audioDeviceOutAllA2dpSet = DeviceTypeSet(
std::begin(AUDIO_DEVICE_OUT_ALL_A2DP_ARRAY),
std::end(AUDIO_DEVICE_OUT_ALL_A2DP_ARRAY));
return audioDeviceOutAllA2dpSet;
}
const DeviceTypeSet& getAudioDeviceOutAllScoSet() {
static const DeviceTypeSet audioDeviceOutAllScoSet = DeviceTypeSet(
std::begin(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY),
std::end(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY));
return audioDeviceOutAllScoSet;
}
const DeviceTypeSet& getAudioDeviceInAllSet() {
static const DeviceTypeSet audioDeviceInAllSet = DeviceTypeSet(
std::begin(AUDIO_DEVICE_IN_ALL_ARRAY),
std::end(AUDIO_DEVICE_IN_ALL_ARRAY));
return audioDeviceInAllSet;
}
bool deviceTypesToString(const DeviceTypeSet &deviceTypes, std::string &str) {
bool ret = true;
for (auto it = deviceTypes.begin(); it != deviceTypes.end();) {
std::string deviceTypeStr;
ret = audio_is_output_device(*it) ?
OutputDeviceConverter::toString(*it, deviceTypeStr) :
InputDeviceConverter::toString(*it, deviceTypeStr);
if (!ret) {
break;
}
str.append(deviceTypeStr);
if (++it != deviceTypes.end()) {
str.append(" , ");
}
}
if (!ret) {
str = "Unknown values";
}
return ret;
}
std::string dumpDeviceTypes(const DeviceTypeSet &deviceTypes) {
std::string ret;
for (auto it = deviceTypes.begin(); it != deviceTypes.end();) {
std::stringstream ss;
ss << "0x" << std::hex << (*it);
ret.append(ss.str());
if (++it != deviceTypes.end()) {
ret.append(" , ");
}
}
return ret;
}
} // namespace android

@ -16,19 +16,37 @@
#pragma once
#include <algorithm>
#include <iterator>
#include <set>
#include <vector>
#include <media/TypeConverter.h>
#include <system/audio.h>
namespace android {
using ChannelMaskSet = std::set<audio_channel_mask_t>;
using DeviceTypeSet = std::set<audio_devices_t>;
using FormatSet = std::set<audio_format_t>;
using SampleRateSet = std::set<uint32_t>;
using FormatVector = std::vector<audio_format_t>;
const DeviceTypeSet& getAudioDeviceOutAllSet();
const DeviceTypeSet& getAudioDeviceOutAllA2dpSet();
const DeviceTypeSet& getAudioDeviceOutAllScoSet();
const DeviceTypeSet& getAudioDeviceInAllSet();
template<typename T>
static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
std::vector<T> intersection;
std::set_intersection(a.begin(), a.end(),
b.begin(), b.end(),
std::back_inserter(intersection));
return intersection;
}
static inline ChannelMaskSet asInMask(const ChannelMaskSet& channelMasks) {
ChannelMaskSet inMaskSet;
for (const auto &channel : channelMasks) {
@ -49,4 +67,55 @@ static inline ChannelMaskSet asOutMask(const ChannelMaskSet& channelMasks) {
return outMaskSet;
}
static inline bool isSingleDeviceType(const DeviceTypeSet& deviceTypes,
audio_devices_t deviceType) {
return deviceTypes.size() == 1 && *(deviceTypes.begin()) == deviceType;
}
typedef bool (*DeviceTypeUnaryPredicate)(audio_devices_t);
static inline bool isSingleDeviceType(const DeviceTypeSet& deviceTypes,
DeviceTypeUnaryPredicate p) {
return deviceTypes.size() == 1 && p(*(deviceTypes.begin()));
}
static inline void resetDeviceTypes(DeviceTypeSet& deviceTypes, audio_devices_t typeToAdd) {
deviceTypes.clear();
deviceTypes.insert(typeToAdd);
}
// FIXME: This is temporary helper function. Remove this when getting rid of all
// bit mask usages of audio device types.
static inline audio_devices_t deviceTypesToBitMask(const DeviceTypeSet& deviceTypes) {
audio_devices_t types = AUDIO_DEVICE_NONE;
for (auto deviceType : deviceTypes) {
types |= deviceType;
}
return types;
}
// FIXME: This is temporary helper function. Remove this when getting rid of all
// bit mask usages of audio device types.
static inline DeviceTypeSet deviceTypesFromBitMask(audio_devices_t types) {
DeviceTypeSet deviceTypes;
if ((types & AUDIO_DEVICE_BIT_IN) == 0) {
for (auto deviceType : AUDIO_DEVICE_OUT_ALL_ARRAY) {
if ((types & deviceType) == deviceType) {
deviceTypes.insert(deviceType);
}
}
} else {
for (auto deviceType : AUDIO_DEVICE_IN_ALL_ARRAY) {
if ((types & deviceType) == deviceType) {
deviceTypes.insert(deviceType);
}
}
}
return deviceTypes;
}
bool deviceTypesToString(const DeviceTypeSet& deviceTypes, std::string &str);
std::string dumpDeviceTypes(const DeviceTypeSet& deviceTypes);
} // namespace android

@ -1,4 +1,7 @@
cc_library_headers {
name: "libaudiopolicycommon",
header_libs: [
"libaudiofoundation_headers",
],
export_include_dirs: ["include"],
}

@ -17,6 +17,7 @@
#pragma once
#include <media/AudioCommonTypes.h>
#include <media/AudioContainers.h>
#include <system/audio.h>
#include <utils/Log.h>
#include <math.h>
@ -82,43 +83,55 @@ public:
*
* @return subset of device required to limit the number of volume category per device
*/
static audio_devices_t getDeviceForVolume(audio_devices_t device)
static audio_devices_t getDeviceForVolume(const android::DeviceTypeSet& deviceTypes)
{
if (device == AUDIO_DEVICE_NONE) {
audio_devices_t deviceType = AUDIO_DEVICE_NONE;
if (deviceTypes.empty()) {
// this happens when forcing a route update and no track is active on an output.
// In this case the returned category is not important.
device = AUDIO_DEVICE_OUT_SPEAKER;
} else if (popcount(device) > 1) {
deviceType = AUDIO_DEVICE_OUT_SPEAKER;
} else if (deviceTypes.size() > 1) {
// Multiple device selection is either:
// - speaker + one other device: give priority to speaker in this case.
// - one A2DP device + another device: happens with duplicated output. In this case
// retain the device on the A2DP output as the other must not correspond to an active
// selection if not the speaker.
// - HDMI-CEC system audio mode only output: give priority to available item in order.
if (device & AUDIO_DEVICE_OUT_SPEAKER) {
device = AUDIO_DEVICE_OUT_SPEAKER;
} else if (device & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
} else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
device = AUDIO_DEVICE_OUT_HDMI_ARC;
} else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
device = AUDIO_DEVICE_OUT_AUX_LINE;
} else if (device & AUDIO_DEVICE_OUT_SPDIF) {
device = AUDIO_DEVICE_OUT_SPDIF;
if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
deviceType = AUDIO_DEVICE_OUT_SPEAKER;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER_SAFE) != 0) {
deviceType = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
deviceType = AUDIO_DEVICE_OUT_HDMI_ARC;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
deviceType = AUDIO_DEVICE_OUT_AUX_LINE;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPDIF) != 0) {
deviceType = AUDIO_DEVICE_OUT_SPDIF;
} else {
device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
std::vector<audio_devices_t> a2dpDevices = android::Intersection(
deviceTypes, android::getAudioDeviceOutAllA2dpSet());
if (a2dpDevices.size() > 1) {
ALOGW("getDeviceForVolume() invalid device combination: %s",
android::dumpDeviceTypes(deviceTypes).c_str());
}
if (!a2dpDevices.empty()) {
deviceType = a2dpDevices[0];
}
}
} else {
deviceType = *(deviceTypes.begin());
}
/*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
device = AUDIO_DEVICE_OUT_SPEAKER;
if (deviceType == AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
deviceType = AUDIO_DEVICE_OUT_SPEAKER;
}
ALOGW_IF(popcount(device) != 1,
"getDeviceForVolume() invalid device combination: %08x",
device);
ALOGW_IF(deviceType == AUDIO_DEVICE_NONE,
"getDeviceForVolume() invalid device combination: %s, returning AUDIO_DEVICE_NONE",
android::dumpDeviceTypes(deviceTypes).c_str());
return device;
return deviceType;
}
/**
@ -128,9 +141,9 @@ public:
*
* @return device category.
*/
static device_category getDeviceCategory(audio_devices_t device)
static device_category getDeviceCategory(const android::DeviceTypeSet& deviceTypes)
{
switch(getDeviceForVolume(device)) {
switch(getDeviceForVolume(deviceTypes)) {
case AUDIO_DEVICE_OUT_EARPIECE:
return DEVICE_CATEGORY_EARPIECE;
case AUDIO_DEVICE_OUT_WIRED_HEADSET:

@ -21,6 +21,7 @@
#include <sys/types.h>
#include <media/AudioContainers.h>
#include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/KeyedVector.h>
@ -156,10 +157,10 @@ public:
virtual DeviceVector supportedDevices() const { return mDevices; }
virtual bool isDuplicated() const { return false; }
virtual uint32_t latency() { return 0; }
virtual bool isFixedVolume(audio_devices_t device);
virtual bool isFixedVolume(const DeviceTypeSet& deviceTypes);
virtual bool setVolume(float volumeDb,
VolumeSource volumeSource, const StreamTypeVector &streams,
audio_devices_t device,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
bool force);
@ -329,10 +330,10 @@ public:
void setDevices(const DeviceVector &devices) { mDevices = devices; }
bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc);
virtual DeviceVector supportedDevices() const;
virtual bool deviceSupportsEncodedFormats(audio_devices_t device);
virtual bool devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes);
virtual uint32_t latency();
virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
virtual bool isFixedVolume(audio_devices_t device);
virtual bool isFixedVolume(const DeviceTypeSet& deviceTypes);
sp<SwAudioOutputDescriptor> subOutput1() { return mOutput1; }
sp<SwAudioOutputDescriptor> subOutput2() { return mOutput2; }
void setClientActive(const sp<TrackClientDescriptor>& client, bool active) override;
@ -344,7 +345,7 @@ public:
}
virtual bool setVolume(float volumeDb,
VolumeSource volumeSource, const StreamTypeVector &streams,
audio_devices_t device,
const DeviceTypeSet& device,
uint32_t delayMs,
bool force);
@ -418,7 +419,7 @@ public:
virtual bool setVolume(float volumeDb,
VolumeSource volumeSource, const StreamTypeVector &streams,
audio_devices_t device,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
bool force);

@ -17,6 +17,7 @@
#pragma once
#include "PolicyAudioPort.h"
#include <media/AudioContainers.h>
#include <media/DeviceDescriptorBase.h>
#include <utils/Errors.h>
#include <utils/String8.h>
@ -93,7 +94,7 @@ private:
class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
{
public:
DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
DeviceVector() : SortedVector() {}
explicit DeviceVector(const sp<DeviceDescriptor>& item) : DeviceVector()
{
add(item);
@ -105,13 +106,16 @@ public:
void remove(const DeviceVector &devices);
ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
audio_devices_t types() const { return mDeviceTypes; }
DeviceTypeSet types() const { return mDeviceTypes; }
// If 'address' is empty and 'codec' is AUDIO_FORMAT_DEFAULT, a device with a non-empty
// address may be returned if there is no device with the specified 'type' and empty address.
sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address,
audio_format_t codec) const;
DeviceVector getDevicesFromTypeMask(audio_devices_t types) const;
DeviceVector getDevicesFromTypes(const DeviceTypeSet& types) const;
DeviceVector getDevicesFromType(audio_devices_t type) const {
return getDevicesFromTypes({type});
}
/**
* @brief getDeviceFromId
@ -122,7 +126,6 @@ public:
sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
sp<DeviceDescriptor> getDeviceFromTagName(const std::string &tagName) const;
DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const;
DeviceVector getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const;
sp<DeviceDescriptor> getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const;
@ -131,6 +134,18 @@ public:
// remove all the devices with the given type and add all the devices to add.
void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd);
bool containsDeviceAmongTypes(const DeviceTypeSet& deviceTypes) const {
return !Intersection(mDeviceTypes, deviceTypes).empty();
}
bool containsDeviceWithType(audio_devices_t deviceType) const {
return containsDeviceAmongTypes({deviceType});
}
bool onlyContainsDevicesWithType(audio_devices_t deviceType) const {
return isSingleDeviceType(mDeviceTypes, deviceType);
}
bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; }
/**
@ -223,7 +238,7 @@ public:
private:
void refreshTypes();
audio_devices_t mDeviceTypes;
DeviceTypeSet mDeviceTypes;
};
} // namespace android

@ -131,8 +131,8 @@ class HwModuleCollection : public Vector<sp<HwModule> >
public:
sp<HwModule> getModuleFromName(const char *name) const;
sp<HwModule> getModuleForDeviceTypes(audio_devices_t device,
audio_format_t encodedFormat) const;
sp<HwModule> getModuleForDeviceType(audio_devices_t device,
audio_format_t encodedFormat) const;
sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device,
audio_format_t encodedFormat) const;

@ -19,6 +19,7 @@
#include "DeviceDescriptor.h"
#include "PolicyAudioPort.h"
#include "policy.h"
#include <media/AudioContainers.h>
#include <utils/String8.h>
#include <system/audio.h>
@ -102,15 +103,12 @@ public:
bool hasSupportedDevices() const { return !mSupportedDevices.isEmpty(); }
bool supportsDeviceTypes(audio_devices_t device) const
bool supportsDeviceTypes(const DeviceTypeSet& deviceTypes) const
{
if (audio_is_output_devices(device)) {
if (deviceSupportsEncodedFormats(device)) {
return mSupportedDevices.types() & device;
}
return false;
}
return mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN);
const bool areOutputDevices = Intersection(deviceTypes, getAudioDeviceInAllSet()).empty();
const bool devicesSupported = !mSupportedDevices.getDevicesFromTypes(deviceTypes).empty();
return devicesSupported &&
(!areOutputDevices || devicesSupportEncodedFormats(deviceTypes));
}
/**
@ -125,18 +123,18 @@ public:
bool supportsDevice(const sp<DeviceDescriptor> &device, bool forceCheckOnAddress = false) const
{
if (!device_distinguishes_on_address(device->type()) && !forceCheckOnAddress) {
return supportsDeviceTypes(device->type());
return supportsDeviceTypes(DeviceTypeSet({device->type()}));
}
return mSupportedDevices.contains(device);
}
bool deviceSupportsEncodedFormats(audio_devices_t device) const
bool devicesSupportEncodedFormats(DeviceTypeSet deviceTypes) const
{
if (device == AUDIO_DEVICE_NONE) {
if (deviceTypes.empty()) {
return true; // required for isOffloadSupported() check
}
DeviceVector deviceList =
mSupportedDevices.getDevicesFromTypeMask(device);
mSupportedDevices.getDevicesFromTypes(deviceTypes);
if (!deviceList.empty()) {
return deviceList.itemAt(0)->hasCurrentEncodedFormat();
}

@ -16,8 +16,9 @@
#pragma once
#include <system/audio.h>
#include <Volume.h>
#include <media/AudioContainers.h>
#include <system/audio.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <vector>
@ -33,7 +34,7 @@ public:
virtual void addCurrentVolumeIndex(audio_devices_t device, int index) = 0;
virtual bool canBeMuted() const = 0;
virtual int getVolumeIndexMin() const = 0;
virtual int getVolumeIndex(audio_devices_t device) const = 0;
virtual int getVolumeIndex(const DeviceTypeSet& device) const = 0;
virtual int getVolumeIndexMax() const = 0;
virtual float volIndexToDb(device_category device, int indexInUi) const = 0;
virtual bool hasVolumeIndexForDevice(audio_devices_t device) const = 0;

@ -30,10 +30,11 @@
// A device mask for all audio output devices that are considered "remote" when evaluating
// active output devices in isStreamActiveRemotely()
#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX
namespace android {
DeviceTypeSet APM_AUDIO_OUT_DEVICE_REMOTE_ALL = {AUDIO_DEVICE_OUT_REMOTE_SUBMIX};
AudioOutputDescriptor::AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
AudioPolicyClientInterface *clientInterface)
: mPolicyAudioPort(policyAudioPort), mClientInterface(clientInterface)
@ -140,7 +141,7 @@ bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
return false;
}
bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
bool AudioOutputDescriptor::isFixedVolume(const DeviceTypeSet& deviceTypes __unused)
{
return false;
}
@ -148,7 +149,7 @@ bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
bool AudioOutputDescriptor::setVolume(float volumeDb,
VolumeSource volumeSource,
const StreamTypeVector &/*streams*/,
audio_devices_t /*device*/,
const DeviceTypeSet& /*deviceTypes*/,
uint32_t delayMs,
bool force)
{
@ -334,13 +335,13 @@ DeviceVector SwAudioOutputDescriptor::filterSupportedDevices(const DeviceVector
return filteredDevices.filter(devices);
}
bool SwAudioOutputDescriptor::deviceSupportsEncodedFormats(audio_devices_t device)
bool SwAudioOutputDescriptor::devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes)
{
if (isDuplicated()) {
return (mOutput1->deviceSupportsEncodedFormats(device)
|| mOutput2->deviceSupportsEncodedFormats(device));
return (mOutput1->devicesSupportEncodedFormats(deviceTypes)
|| mOutput2->devicesSupportEncodedFormats(deviceTypes));
} else {
return mProfile->deviceSupportsEncodedFormats(device);
return mProfile->devicesSupportEncodedFormats(deviceTypes);
}
}
@ -363,16 +364,16 @@ void SwAudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& c
AudioOutputDescriptor::setClientActive(client, active);
}
bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
bool SwAudioOutputDescriptor::isFixedVolume(const DeviceTypeSet& deviceTypes)
{
// unit gain if rerouting to external policy
if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
if (isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
if (mPolicyMix != NULL) {
ALOGV("max gain when rerouting for output=%d", mIoHandle);
return true;
}
}
if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
if (isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
ALOGV("max gain when output device is telephony tx");
return true;
}
@ -405,12 +406,12 @@ void SwAudioOutputDescriptor::toAudioPort(
bool SwAudioOutputDescriptor::setVolume(float volumeDb,
VolumeSource vs, const StreamTypeVector &streamTypes,
audio_devices_t device,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
bool force)
{
StreamTypeVector streams = streamTypes;
if (!AudioOutputDescriptor::setVolume(volumeDb, vs, streamTypes, device, delayMs, force)) {
if (!AudioOutputDescriptor::setVolume(volumeDb, vs, streamTypes, deviceTypes, delayMs, force)) {
return false;
}
if (streams.empty()) {
@ -420,7 +421,7 @@ bool SwAudioOutputDescriptor::setVolume(float volumeDb,
// APM loops on all group, so filter on active group to set the port gain,
// let the other groups set the stream volume as per legacy
// TODO: Pass in the device address and check against it.
if (device == devicePort->type() &&
if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
devicePort->hasGainController(true) && isActive(vs)) {
ALOGV("%s: device %s has gain controller", __func__, devicePort->toString().c_str());
// @todo: here we might be in trouble if the SwOutput has several active clients with
@ -467,7 +468,7 @@ status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
{
mDevices = devices;
const String8& address = devices.getFirstValidAddress();
audio_devices_t device = devices.types();
DeviceTypeSet deviceTypes = devices.types();
audio_config_t lConfig;
if (config == nullptr) {
@ -499,21 +500,25 @@ status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
ALOGV("opening output for device %s profile %p name %s",
mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
// FIXME: Stop using device types as bit mask when the interface updated.
audio_devices_t deviceType = deviceTypesToBitMask(deviceTypes);
status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
output,
&lConfig,
&device,
&deviceType,
address,
&mLatency,
mFlags);
LOG_ALWAYS_FATAL_IF(mDevices.types() != device,
"%s openOutput returned device %08x when given device %08x",
__FUNCTION__, mDevices.types(), device);
deviceTypes = deviceTypesFromBitMask(deviceType);
LOG_ALWAYS_FATAL_IF(mDevices.types() != deviceTypes,
"%s openOutput returned device %s when given device %s",
__FUNCTION__, dumpDeviceTypes(mDevices.types()).c_str(),
dumpDeviceTypes(deviceTypes).c_str());
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
"%s openOutput returned output handle %d for device %08x",
__FUNCTION__, *output, device);
"%s openOutput returned output handle %d for device %s",
__FUNCTION__, *output, dumpDeviceTypes(deviceTypes).c_str());
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
@ -646,12 +651,12 @@ void HwAudioOutputDescriptor::toAudioPort(
bool HwAudioOutputDescriptor::setVolume(float volumeDb,
VolumeSource volumeSource, const StreamTypeVector &streams,
audio_devices_t device,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
bool force)
{
bool changed =
AudioOutputDescriptor::setVolume(volumeDb, volumeSource, streams, device, delayMs, force);
bool changed = AudioOutputDescriptor::setVolume(
volumeDb, volumeSource, streams, deviceTypes, delayMs, force);
if (changed) {
// TODO: use gain controller on source device if any to adjust volume
@ -678,7 +683,8 @@ bool SwAudioOutputCollection::isActiveLocally(VolumeSource volumeSource, uint32_
for (size_t i = 0; i < this->size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
&& ((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
&& (!(outputDesc->devices()
.containsDeviceAmongTypes(APM_AUDIO_OUT_DEVICE_REMOTE_ALL)))) {
return true;
}
}
@ -690,7 +696,7 @@ bool SwAudioOutputCollection::isActiveRemotely(VolumeSource volumeSource, uint32
nsecs_t sysTime = systemTime();
for (size_t i = 0; i < size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
if (((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
if (outputDesc->devices().containsDeviceAmongTypes(APM_AUDIO_OUT_DEVICE_REMOTE_ALL) &&
outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
// do not consider re routing (when the output is going to a dynamic policy)
// as "remote playback"
@ -721,9 +727,8 @@ audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const
for (size_t i = 0; i < size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
if (!outputDesc->isDuplicated() &&
outputDesc->devices().types() & AUDIO_DEVICE_OUT_ALL_A2DP &&
outputDesc->deviceSupportsEncodedFormats(
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
outputDesc->devices().containsDeviceAmongTypes(getAudioDeviceOutAllA2dpSet()) &&
outputDesc->devicesSupportEncodedFormats(getAudioDeviceOutAllA2dpSet())) {
return this->keyAt(i);
}
}
@ -739,7 +744,7 @@ bool SwAudioOutputCollection::isA2dpOffloadedOnPrimary() const
sp<HwModule> primaryHwModule = primaryOutput->mProfile->getModule();
for (const auto &outputProfile : primaryHwModule->getOutputProfiles()) {
if (outputProfile->supportsDeviceTypes(AUDIO_DEVICE_OUT_ALL_A2DP)) {
if (outputProfile->supportsDeviceTypes(getAudioDeviceOutAllA2dpSet())) {
return true;
}
}

@ -164,11 +164,11 @@ void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) c
void DeviceVector::refreshTypes()
{
mDeviceTypes = AUDIO_DEVICE_NONE;
mDeviceTypes.clear();
for (size_t i = 0; i < size(); i++) {
mDeviceTypes |= itemAt(i)->type();
mDeviceTypes.insert(itemAt(i)->type());
}
ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
ALOGV("DeviceVector::refreshTypes() mDeviceTypes %s", dumpDeviceTypes(mDeviceTypes).c_str());
}
ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
@ -243,17 +243,6 @@ DeviceVector DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHa
return devices;
}
audio_devices_t DeviceVector::getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const
{
audio_devices_t deviceTypes = AUDIO_DEVICE_NONE;
for (const auto& device : *this) {
if (device->getModuleHandle() == moduleHandle) {
deviceTypes |= device->type();
}
}
return deviceTypes;
}
sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address,
audio_format_t format) const
{
@ -290,15 +279,14 @@ sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
return nullptr;
}
DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const
DeviceVector DeviceVector::getDevicesFromTypes(const DeviceTypeSet& types) const
{
DeviceVector devices;
bool isOutput = audio_is_output_devices(type);
type &= ~AUDIO_DEVICE_BIT_IN;
for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
bool curIsOutput = audio_is_output_devices(itemAt(i)->type());
audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
if (types.empty()) {
return devices;
}
for (size_t i = 0; i < size(); i++) {
if (types.count(itemAt(i)->type()) != 0) {
devices.add(itemAt(i));
ALOGV("DeviceVector::%s() for type %08x found %p",
__func__, itemAt(i)->type(), itemAt(i).get());
@ -322,7 +310,7 @@ DeviceVector DeviceVector::getFirstDevicesFromTypes(
{
DeviceVector devices;
for (auto deviceType : orderedTypes) {
if (!(devices = getDevicesFromTypeMask(deviceType)).isEmpty()) {
if (!(devices = getDevicesFromType(deviceType)).isEmpty()) {
break;
}
}
@ -342,7 +330,7 @@ sp<DeviceDescriptor> DeviceVector::getFirstExistingDevice(
void DeviceVector::replaceDevicesByType(
audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
DeviceVector devicesToRemove = getDevicesFromTypeMask(typeToRemove);
DeviceVector devicesToRemove = getDevicesFromType(typeToRemove);
if (!devicesToRemove.isEmpty() && !devicesToAdd.isEmpty()) {
remove(devicesToRemove);
add(devicesToAdd);

@ -273,14 +273,14 @@ sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
return nullptr;
}
sp <HwModule> HwModuleCollection::getModuleForDeviceTypes(audio_devices_t type,
audio_format_t encodedFormat) const
sp <HwModule> HwModuleCollection::getModuleForDeviceType(audio_devices_t type,
audio_format_t encodedFormat) const
{
for (const auto& module : *this) {
const auto& profiles = audio_is_output_device(type) ?
module->getOutputProfiles() : module->getInputProfiles();
for (const auto& profile : profiles) {
if (profile->supportsDeviceTypes(type)) {
if (profile->supportsDeviceTypes({type})) {
if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
DeviceVector declaredDevices = module->getDeclaredDevices();
sp <DeviceDescriptor> deviceDesc =
@ -300,7 +300,7 @@ sp <HwModule> HwModuleCollection::getModuleForDeviceTypes(audio_devices_t type,
sp<HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device,
audio_format_t encodedFormat) const
{
return getModuleForDeviceTypes(device->type(), encodedFormat);
return getModuleForDeviceType(device->type(), encodedFormat);
}
DeviceVector HwModuleCollection::getAvailableDevicesFromModuleName(
@ -354,7 +354,7 @@ sp<DeviceDescriptor> HwModuleCollection::createDevice(const audio_devices_t type
const char *name,
const audio_format_t encodedFormat) const
{
sp<HwModule> hwModule = getModuleForDeviceTypes(type, encodedFormat);
sp<HwModule> hwModule = getModuleForDeviceType(type, encodedFormat);
if (hwModule == 0) {
ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type,
address);

@ -44,4 +44,7 @@ cc_library_static {
"libaudiopolicycomponents",
"libaudiopolicyengine_config",
],
shared_libs: [
"libaudiofoundation",
],
}

@ -27,6 +27,7 @@
#include <utils/Errors.h>
#include <utils/String8.h>
#include <media/AudioAttributes.h>
#include <media/AudioContainers.h>
namespace android {
@ -77,12 +78,12 @@ public:
std::string getDeviceAddress() const { return mDeviceAddress; }
void setDeviceTypes(audio_devices_t devices)
void setDeviceTypes(const DeviceTypeSet& devices)
{
mApplicableDevices = devices;
}
audio_devices_t getDeviceTypes() const { return mApplicableDevices; }
DeviceTypeSet getDeviceTypes() const { return mApplicableDevices; }
audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
@ -109,7 +110,7 @@ private:
/**
* Applicable device(s) type mask for this strategy.
*/
audio_devices_t mApplicableDevices = AUDIO_DEVICE_NONE;
DeviceTypeSet mApplicableDevices;
};
class ProductStrategyMap : public std::map<product_strategy_t, sp<ProductStrategy> >
@ -144,7 +145,7 @@ public:
*/
audio_attributes_t getAttributesForProductStrategy(product_strategy_t strategy) const;
audio_devices_t getDeviceTypesForProductStrategy(product_strategy_t strategy) const;
DeviceTypeSet getDeviceTypesForProductStrategy(product_strategy_t strategy) const;
std::string getDeviceAddressForProductStrategy(product_strategy_t strategy) const;

@ -91,9 +91,9 @@ public:
return valueFor(device);
}
virtual int getVolumeIndex(audio_devices_t device) const
virtual int getVolumeIndex(const DeviceTypeSet& deviceTypes) const
{
device = Volume::getDeviceForVolume(device);
audio_devices_t device = Volume::getDeviceForVolume(deviceTypes);
// there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME
if (mIndexCur.find(device) == end(mIndexCur)) {
device = AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME;
@ -114,7 +114,7 @@ public:
bool hasVolumeIndexForDevice(audio_devices_t device) const
{
device = Volume::getDeviceForVolume(device);
device = Volume::getDeviceForVolume({device});
return mIndexCur.find(device) != end(mIndexCur);
}

@ -143,8 +143,9 @@ void ProductStrategy::dump(String8 *dst, int spaces) const
{
dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
std::string deviceLiteral;
if (!OutputDeviceConverter::toString(mApplicableDevices, deviceLiteral)) {
ALOGE("%s: failed to convert device %d", __FUNCTION__, mApplicableDevices);
if (!deviceTypesToString(mApplicableDevices, deviceLiteral)) {
ALOGE("%s: failed to convert device %s",
__FUNCTION__, dumpDeviceTypes(mApplicableDevices).c_str());
}
dst->appendFormat("%*sSelected Device: {type:%s, @:%s}\n", spaces + 2, "",
deviceLiteral.c_str(), mDeviceAddress.c_str());
@ -236,14 +237,14 @@ product_strategy_t ProductStrategyMap::getProductStrategyForStream(audio_stream_
}
audio_devices_t ProductStrategyMap::getDeviceTypesForProductStrategy(
DeviceTypeSet ProductStrategyMap::getDeviceTypesForProductStrategy(
product_strategy_t strategy) const
{
if (find(strategy) == end()) {
ALOGE("Invalid %d strategy requested, returning device for default strategy", strategy);
product_strategy_t defaultStrategy = getDefault();
if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
return AUDIO_DEVICE_NONE;
return {AUDIO_DEVICE_NONE};
}
return at(getDefault())->getDeviceTypes();
}

@ -32,6 +32,7 @@
#include <policy.h>
#include <AudioIODescriptorInterface.h>
#include <ParameterManagerWrapper.h>
#include <media/AudioContainers.h>
#include <media/TypeConverter.h>
@ -167,11 +168,13 @@ status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
mPolicyParameterMgr->setDeviceConnectionState(devDesc, state);
if (audio_is_output_device(devDesc->type())) {
// FIXME: Use DeviceTypeSet when the interface is ready
return mPolicyParameterMgr->setAvailableOutputDevices(
getApmObserver()->getAvailableOutputDevices().types());
deviceTypesToBitMask(getApmObserver()->getAvailableOutputDevices().types()));
} else if (audio_is_input_device(devDesc->type())) {
// FIXME: Use DeviceTypeSet when the interface is ready
return mPolicyParameterMgr->setAvailableInputDevices(
getApmObserver()->getAvailableInputDevices().types());
deviceTypesToBitMask(getApmObserver()->getAvailableInputDevices().types()));
}
return BAD_TYPE;
}
@ -211,7 +214,7 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t ps) const
}
const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
uint32_t availableOutputDevicesType = availableOutputDevices.types();
DeviceTypeSet availableOutputDevicesTypes = availableOutputDevices.types();
/** This is the only case handled programmatically because the PFW is unable to know the
* activity of streams.
@ -223,7 +226,7 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t ps) const
*
* -When media is not playing anymore, fall back on the sonification behavior
*/
audio_devices_t devices = AUDIO_DEVICE_NONE;
DeviceTypeSet deviceTypes;
if (ps == getProductStrategyForStream(AUDIO_STREAM_NOTIFICATION) &&
!is_state_in_call(getPhoneState()) &&
!outputs.isActiveRemotely(toVolumeSource(AUDIO_STREAM_MUSIC),
@ -232,7 +235,7 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t ps) const
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
product_strategy_t strategyForMedia =
getProductStrategyForStream(AUDIO_STREAM_MUSIC);
devices = productStrategies.getDeviceTypesForProductStrategy(strategyForMedia);
deviceTypes = productStrategies.getDeviceTypesForProductStrategy(strategyForMedia);
} else if (ps == getProductStrategyForStream(AUDIO_STREAM_ACCESSIBILITY) &&
(outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM)))) {
@ -240,36 +243,37 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t ps) const
// compressed format as they would likely not be mixed and dropped.
// Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.
product_strategy_t strategyNotification = getProductStrategyForStream(AUDIO_STREAM_RING);
devices = productStrategies.getDeviceTypesForProductStrategy(strategyNotification);
deviceTypes = productStrategies.getDeviceTypesForProductStrategy(strategyNotification);
} else {
devices = productStrategies.getDeviceTypesForProductStrategy(ps);
deviceTypes = productStrategies.getDeviceTypesForProductStrategy(ps);
}
if (devices == AUDIO_DEVICE_NONE ||
(devices & availableOutputDevicesType) == AUDIO_DEVICE_NONE) {
if (deviceTypes.empty() ||
Intersection(deviceTypes, availableOutputDevicesTypes).empty()) {
auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
ALOG_ASSERT(defaultDevice != nullptr, "no valid default device defined");
return DeviceVector(defaultDevice);
}
if (/*device_distinguishes_on_address(devices)*/ devices == AUDIO_DEVICE_OUT_BUS) {
if (/*device_distinguishes_on_address(*deviceTypes.begin())*/ isSingleDeviceType(
deviceTypes, AUDIO_DEVICE_OUT_BUS)) {
// We do expect only one device for these types of devices
// Criterion device address garantee this one is available
// If this criterion is not wished, need to ensure this device is available
const String8 address(productStrategies.getDeviceAddressForProductStrategy(ps).c_str());
ALOGV("%s:device 0x%x %s %d", __FUNCTION__, devices, address.c_str(), ps);
auto busDevice = availableOutputDevices.getDevice(devices, address, AUDIO_FORMAT_DEFAULT);
ALOGV("%s:device %s %s %d",
__FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), address.c_str(), ps);
auto busDevice = availableOutputDevices.getDevice(
*deviceTypes.begin(), address, AUDIO_FORMAT_DEFAULT);
if (busDevice == nullptr) {
ALOGE("%s:unavailable device 0x%x %s, fallback on default", __func__, devices,
address.c_str());
ALOGE("%s:unavailable device %s %s, fallback on default", __func__,
dumpDeviceTypes(deviceTypes).c_str(), address.c_str());
auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
ALOG_ASSERT(defaultDevice != nullptr, "Default Output Device NOT available");
return DeviceVector(defaultDevice);
}
return DeviceVector(availableOutputDevices.getDevice(devices,
address,
AUDIO_FORMAT_DEFAULT));
return DeviceVector(busDevice);
}
ALOGV("%s:device 0x%x %d", __FUNCTION__, devices, ps);
return availableOutputDevices.getDevicesFromTypeMask(devices);
ALOGV("%s:device %s %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), ps);
return availableOutputDevices.getDevicesFromTypes(deviceTypes);
}
DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
@ -366,7 +370,8 @@ bool Engine::setDeviceTypesForProductStrategy(product_strategy_t strategy, audio
ALOGE("%s: set device %d on invalid strategy %d", __FUNCTION__, devices, strategy);
return false;
}
getProductStrategies().at(strategy)->setDeviceTypes(devices);
// FIXME: stop using deviceTypesFromBitMask when the interface is ready
getProductStrategies().at(strategy)->setDeviceTypes(deviceTypesFromBitMask(devices));
return true;
}

@ -31,6 +31,7 @@
#include <IOProfile.h>
#include <AudioIODescriptorInterface.h>
#include <policy.h>
#include <media/AudioContainers.h>
#include <utils/String8.h>
#include <utils/Log.h>
@ -146,7 +147,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
switch (strategy) {
case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
break;
case STRATEGY_SONIFICATION_RESPECTFUL:
@ -161,7 +162,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
// routing is same as media without the "remote" device
availableOutputDevices.remove(availableOutputDevices.getDevicesFromTypeMask(
availableOutputDevices.remove(availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_REMOTE_SUBMIX));
devices = getDevicesForStrategyInt(STRATEGY_MEDIA,
availableOutputDevices,
@ -171,7 +172,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
if (!media_active_locally) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
availableOutputDevices.getDevicesFromTypeMask(
availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
}
}
@ -203,10 +204,10 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
// audio_policy_configuration.xml, hearing aid is not there, but it's
// a primary device
// FIXME: this is not the right way of solving this problem
DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypeMask(
DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypes(
primaryOutput->supportedDevices().types());
availPrimaryOutputDevices.add(
availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID));
availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
@ -221,7 +222,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
case AUDIO_POLICY_FORCE_BT_SCO:
if (!isInCall() || strategy != STRATEGY_DTMF) {
devices = availableOutputDevices.getDevicesFromTypeMask(
devices = availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
if (!devices.isEmpty()) break;
}
@ -232,7 +233,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
FALLTHROUGH_INTENDED;
default: // FORCE_NONE
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
if (!devices.isEmpty()) break;
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
if (!isInCall() &&
@ -254,7 +255,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
if (!devices.isEmpty()) break;
}
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_EARPIECE);
devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
break;
case AUDIO_POLICY_FORCE_SPEAKER:
@ -263,7 +264,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
if (!isInCall() &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
outputs.isA2dpSupported()) {
devices = availableOutputDevices.getDevicesFromTypeMask(
devices = availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
if (!devices.isEmpty()) break;
}
@ -274,7 +275,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
if (!devices.isEmpty()) break;
}
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
break;
}
break;
@ -298,12 +299,12 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
if ((strategy == STRATEGY_SONIFICATION) ||
(getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
devices = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
// if SCO headset is connected and we are told to use it, play ringtone over
// speaker and BT SCO
if (!availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_ALL_SCO).isEmpty()) {
if (!availableOutputDevices.getDevicesFromTypes(getAudioDeviceOutAllScoSet()).isEmpty()) {
DeviceVector devices2;
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
@ -324,7 +325,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
if (strategy == STRATEGY_SONIFICATION) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
availableOutputDevices.getDevicesFromTypeMask(
availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
}
if (!devices2.isEmpty()) {
@ -343,9 +344,9 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
for (size_t i = 0; i < outputs.size(); i++) {
sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) {
availableOutputDevices.remove(desc->devices().getDevicesFromTypeMask(
AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF
| AUDIO_DEVICE_OUT_HDMI_ARC));
availableOutputDevices.remove(desc->devices().getDevicesFromTypes({
AUDIO_DEVICE_OUT_HDMI, AUDIO_DEVICE_OUT_SPDIF,
AUDIO_DEVICE_OUT_HDMI_ARC}));
}
}
if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
@ -382,7 +383,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
// FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261).
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_HEARING_AID);
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
}
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
@ -393,7 +394,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
}
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
if (devices2.isEmpty()) {
devices2 = availableOutputDevices.getFirstDevicesFromTypes({
@ -404,21 +405,21 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
}
if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
// no sonification on aux digital (e.g. HDMI)
devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_AUX_DIGITAL);
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_AUX_DIGITAL);
}
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
devices2 = availableOutputDevices.getDevicesFromTypeMask(
devices2 = availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
}
if (devices2.isEmpty()) {
devices2 = availableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER);
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
DeviceVector devices3;
if (strategy == STRATEGY_MEDIA) {
// ARC, SPDIF and AUX_LINE can co-exist with others.
devices3 = availableOutputDevices.getDevicesFromTypeMask(
AUDIO_DEVICE_OUT_HDMI_ARC | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_AUX_LINE);
devices3 = availableOutputDevices.getDevicesFromTypes({
AUDIO_DEVICE_OUT_HDMI_ARC, AUDIO_DEVICE_OUT_SPDIF, AUDIO_DEVICE_OUT_AUX_LINE});
}
devices2.add(devices3);
@ -430,7 +431,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
if ((strategy == STRATEGY_MEDIA) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) ==
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
devices.remove(devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
devices.remove(devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
}
// for STRATEGY_SONIFICATION:
@ -438,7 +439,7 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
if (strategy == STRATEGY_SONIFICATION) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
availableOutputDevices.getDevicesFromTypeMask(
availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_SPEAKER_SAFE));
}
} break;

@ -425,7 +425,7 @@ status_t AudioPolicyManager::handleDeviceConfigChange(audio_devices_t device,
if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
// Check if the device is currently connected
DeviceVector deviceList = mAvailableOutputDevices.getDevicesFromTypeMask(device);
DeviceVector deviceList = mAvailableOutputDevices.getDevicesFromType(device);
if (deviceList.empty()) {
// Nothing to do: device is not connected
return NO_ERROR;
@ -439,8 +439,8 @@ status_t AudioPolicyManager::handleDeviceConfigChange(audio_devices_t device,
// Case 1: A2DP active device switches from primary to primary
// module
// Case 2: A2DP device config changes on primary module.
if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
sp<HwModule> module = mHwModules.getModuleForDeviceTypes(device, encodedFormat);
if (audio_is_a2dp_out_device(device)) {
sp<HwModule> module = mHwModules.getModuleForDeviceType(device, encodedFormat);
audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
if (availablePrimaryOutputDevices().contains(devDesc) &&
(module != 0 && module->getHandle() == primaryHandle)) {
@ -496,8 +496,8 @@ status_t AudioPolicyManager::getHwOffloadEncodingFormatsSupportedForA2DP(
ALOGE("%s() unable to get primary module", __func__);
return NO_INIT;
}
DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypeMask(
AUDIO_DEVICE_OUT_ALL_A2DP);
DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypes(
getAudioDeviceOutAllA2dpSet());
for (const auto& device : declaredDevices) {
formatSet.insert(device->encodedFormats().begin(), device->encodedFormats().end());
}
@ -511,7 +511,8 @@ uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, ui
bool createRxPatch = false;
uint32_t muteWaitMs = 0;
if(!hasPrimaryOutput() || mPrimaryOutput->devices().types() == AUDIO_DEVICE_OUT_STUB) {
if(!hasPrimaryOutput() ||
mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) {
return muteWaitMs;
}
ALOG_ASSERT(!rxDevices.isEmpty(), "updateCallRouting() no selected output device");
@ -535,9 +536,9 @@ uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, ui
}
auto telephonyRxModule =
mHwModules.getModuleForDeviceTypes(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
auto telephonyTxModule =
mHwModules.getModuleForDeviceTypes(AUDIO_DEVICE_OUT_TELEPHONY_TX, AUDIO_FORMAT_DEFAULT);
mHwModules.getModuleForDeviceType(AUDIO_DEVICE_OUT_TELEPHONY_TX, AUDIO_FORMAT_DEFAULT);
// retrieve Rx Source and Tx Sink device descriptors
sp<DeviceDescriptor> rxSourceDevice =
mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
@ -648,20 +649,6 @@ sp<AudioPatch> AudioPolicyManager::createTelephonyPatch(
return audioPatch;
}
sp<DeviceDescriptor> AudioPolicyManager::findDevice(
const DeviceVector& devices, audio_devices_t device) const {
DeviceVector deviceList = devices.getDevicesFromTypeMask(device);
ALOG_ASSERT(!deviceList.isEmpty(),
"%s() selected device type %#x is not in devices list", __func__, device);
return deviceList.itemAt(0);
}
audio_devices_t AudioPolicyManager::getModuleDeviceTypes(
const DeviceVector& devices, const char *moduleId) const {
sp<HwModule> mod = mHwModules.getModuleFromName(moduleId);
return mod != 0 ? devices.getDeviceTypesFromHwModule(mod->getHandle()) : AUDIO_DEVICE_NONE;
}
bool AudioPolicyManager::isDeviceOfModule(
const sp<DeviceDescriptor>& devDesc, const char *moduleId) const {
sp<HwModule> module = mHwModules.getModuleFromName(moduleId);
@ -881,7 +868,7 @@ sp<IOProfile> AudioPolicyManager::getProfileForOutput(
continue;
}
// reject profiles if connected device does not support codec
if (!curProfile->deviceSupportsEncodedFormats(devices.types())) {
if (!curProfile->devicesSupportEncodedFormats(devices.types())) {
continue;
}
if (!directOnly) return curProfile;
@ -1025,7 +1012,7 @@ status_t AudioPolicyManager::getOutputForAttrInt(
// FIXME: provide a more generic approach which is not device specific and move this back
// to getOutputForDevice.
// TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side.
if (outputDevices.types() == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX) &&
(*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
audio_is_linear_pcm(config->format) &&
isInCall()) {
@ -1235,7 +1222,7 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevices(
for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
const struct audio_port_config *sink = &patch->mPatch.sinks[j];
if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
(sink->ext.device.type & devices.types()) != AUDIO_DEVICE_NONE &&
devices.containsDeviceWithType(sink->ext.device.type) &&
(address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
releaseAudioPatch(patch->mHandle, mUidCached);
@ -1778,14 +1765,15 @@ status_t AudioPolicyManager::startSource(const sp<SwAudioOutputDescriptor>& outp
}
if (stream == AUDIO_STREAM_ENFORCED_AUDIBLE &&
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
mEngine->getForceUse(
AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
setStrategyMute(streamToStrategy(AUDIO_STREAM_ALARM), true, outputDesc);
}
// Automatically enable the remote submix input when output is started on a re routing mix
// of type MIX_TYPE_RECORDERS
if (audio_is_remote_submix_device(devices.types()) && policyMix != NULL &&
policyMix->mMixType == MIX_TYPE_RECORDERS) {
if (isSingleDeviceType(devices.types(), &audio_is_remote_submix_device) &&
policyMix != NULL && policyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address,
@ -1832,7 +1820,8 @@ status_t AudioPolicyManager::stopSource(const sp<SwAudioOutputDescriptor>& outpu
// Automatically disable the remote submix input when output is stopped on a
// re routing mix of type MIX_TYPE_RECORDERS
sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
if (audio_is_remote_submix_device(outputDesc->devices().types()) &&
if (isSingleDeviceType(
outputDesc->devices().types(), &audio_is_remote_submix_device) &&
policyMix != NULL &&
policyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
@ -2492,10 +2481,12 @@ status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream,
{
// if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
// stream by the engine.
DeviceTypeSet deviceTypes = {device};
if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
device = mEngine->getOutputDevicesForStream(stream, true /*fromCache*/).types();
deviceTypes = mEngine->getOutputDevicesForStream(
stream, true /*fromCache*/).types();
}
return getVolumeIndex(getVolumeCurves(stream), *index, device);
return getVolumeIndex(getVolumeCurves(stream), *index, deviceTypes);
}
status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attributes,
@ -2520,19 +2511,20 @@ status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_
return status;
}
audio_devices_t curSrcDevice;
DeviceTypeSet curSrcDevices;
auto curCurvAttrs = curves.getAttributes();
if (!curCurvAttrs.empty() && curCurvAttrs.front() != defaultAttr) {
auto attr = curCurvAttrs.front();
curSrcDevice = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
curSrcDevices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
} else if (!curves.getStreamTypes().empty()) {
auto stream = curves.getStreamTypes().front();
curSrcDevice = mEngine->getOutputDevicesForStream(stream, false).types();
curSrcDevices = mEngine->getOutputDevicesForStream(stream, false).types();
} else {
ALOGE("%s: Invalid src %d: no valid attributes nor stream",__func__, vs);
return BAD_VALUE;
}
curSrcDevice = Volume::getDeviceForVolume(curSrcDevice);
audio_devices_t curSrcDevice = Volume::getDeviceForVolume(curSrcDevices);
resetDeviceTypes(curSrcDevices, curSrcDevice);
// update volume on all outputs and streams matching the following:
// - The requested stream (or a stream matching for volume control) is active on the output
@ -2544,11 +2536,10 @@ status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_
// no specific device volume value exists for currently selected device.
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
audio_devices_t curDevice = desc->devices().types();
DeviceTypeSet curDevices = desc->devices().types();
if (curDevice & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
curDevice |= AUDIO_DEVICE_OUT_SPEAKER;
curDevice &= ~AUDIO_DEVICE_OUT_SPEAKER_SAFE;
if (curDevices.erase(AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
curDevices.insert(AUDIO_DEVICE_OUT_SPEAKER);
}
// Inter / intra volume group priority management: Loop on strategies arranged by priority
@ -2592,7 +2583,7 @@ status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_
if (!applyVolume) {
continue; // next output
}
status_t volStatus = checkAndSetVolume(curves, vs, index, desc, curDevice,
status_t volStatus = checkAndSetVolume(curves, vs, index, desc, curDevices,
(vs == toVolumeSource(AUDIO_STREAM_SYSTEM)?
TOUCH_SOUND_FIXED_DELAY_MS : 0));
if (volStatus != NO_ERROR) {
@ -2603,12 +2594,14 @@ status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_
if (!(desc->isActive(vs) || isInCall())) {
continue;
}
if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) && ((curDevice & device) == 0)) {
if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME &&
curDevices.find(device) == curDevices.end()) {
continue;
}
if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
curSrcDevice |= device;
applyVolume = (Volume::getDeviceForVolume(curDevice) & curSrcDevice) != 0;
curSrcDevices.insert(device);
applyVolume = (curSrcDevices.find(
Volume::getDeviceForVolume(curDevices)) != curSrcDevices.end());
} else {
applyVolume = !curves.hasVolumeIndexForDevice(curSrcDevice);
}
@ -2617,7 +2610,7 @@ status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_
// delayed volume change for system stream to be removed when the problem is
// handled by system UI
status_t volStatus = checkAndSetVolume(
curves, vs, index, desc, curDevice,
curves, vs, index, desc, curDevices,
((vs == toVolumeSource(AUDIO_STREAM_SYSTEM))?
TOUCH_SOUND_FIXED_DELAY_MS : 0));
if (volStatus != NO_ERROR) {
@ -2660,22 +2653,23 @@ status_t AudioPolicyManager::getVolumeIndexForAttributes(const audio_attributes_
{
// if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
// stream by the engine.
DeviceTypeSet deviceTypes = {device};
if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
device = mEngine->getOutputDevicesForAttributes(attr, nullptr, true /*fromCache*/).types();
DeviceTypeSet deviceTypes = mEngine->getOutputDevicesForAttributes(
attr, nullptr, true /*fromCache*/).types();
}
return getVolumeIndex(getVolumeCurves(attr), index, device);
return getVolumeIndex(getVolumeCurves(attr), index, deviceTypes);
}
status_t AudioPolicyManager::getVolumeIndex(const IVolumeCurves &curves,
int &index,
audio_devices_t device) const
const DeviceTypeSet& deviceTypes) const
{
if (!audio_is_output_device(device)) {
if (isSingleDeviceType(deviceTypes, audio_is_output_device)) {
return BAD_VALUE;
}
device = Volume::getDeviceForVolume(device);
index = curves.getVolumeIndex(device);
ALOGV("%s: device %08x index %d", __FUNCTION__, device, index);
index = curves.getVolumeIndex(deviceTypes);
ALOGV("%s: device %s index %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), index);
return NO_ERROR;
}
@ -3439,8 +3433,8 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
}
// TODO: reconfigure output format and channels here
ALOGV("createAudioPatch() setting device %08x on output %d",
devices.types(), outputDesc->mIoHandle);
ALOGV("createAudioPatch() setting device %s on output %d",
dumpDeviceTypes(devices.types()).c_str(), outputDesc->mIoHandle);
setOutputDevices(outputDesc, devices, true, 0, handle);
index = mAudioPatches.indexOfKey(*handle);
if (index >= 0) {
@ -3920,12 +3914,14 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>
&selectedDeviceId, &isRequestedDeviceForExclusiveUse,
&secondaryOutputs);
if (output == AUDIO_IO_HANDLE_NONE) {
ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevices.types());
ALOGV("%s no output for device %s",
__FUNCTION__, dumpDeviceTypes(sinkDevices.types()).c_str());
return INVALID_OPERATION;
}
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc->isDuplicated()) {
ALOGV("%s output for device %08x is duplicated", __FUNCTION__, sinkDevices.types());
ALOGV("%s output for device %s is duplicated",
__FUNCTION__, dumpDeviceTypes(sinkDevices.types()).c_str());
return INVALID_OPERATION;
}
status_t status = outputDesc->start();
@ -4034,7 +4030,7 @@ status_t AudioPolicyManager::getMasterMono(bool *mono)
float AudioPolicyManager::getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device)
{
return computeVolume(getVolumeCurves(stream), toVolumeSource(stream), index, device);
return computeVolume(getVolumeCurves(stream), toVolumeSource(stream), index, {device});
}
status_t AudioPolicyManager::getSurroundFormats(unsigned int *numSurroundFormats,
@ -4134,8 +4130,8 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat
sp<SwAudioOutputDescriptor> outputDesc;
bool profileUpdated = false;
DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(
AUDIO_DEVICE_OUT_HDMI);
DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_HDMI);
for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
String8 address = String8(hdmiOutputDevices[i]->address().c_str());
@ -4156,7 +4152,7 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat
profileUpdated |= (status == NO_ERROR);
}
// FIXME: Why doing this for input HDMI devices if we don't augment their reported formats?
DeviceVector hdmiInputDevices = mAvailableInputDevices.getDevicesFromTypeMask(
DeviceVector hdmiInputDevices = mAvailableInputDevices.getDevicesFromType(
AUDIO_DEVICE_IN_HDMI);
for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
@ -4552,7 +4548,7 @@ void AudioPolicyManager::addOutput(audio_io_handle_t output,
const sp<SwAudioOutputDescriptor>& outputDesc)
{
mOutputs.add(output, outputDesc);
applyStreamVolumes(outputDesc, AUDIO_DEVICE_NONE, 0 /* delayMs */, true /* force */);
applyStreamVolumes(outputDesc, DeviceTypeSet(), 0 /* delayMs */, true /* force */);
updateMono(output); // update mono status when adding to output list
selectOutputForMusicEffects();
nextAudioPortGeneration();
@ -4589,7 +4585,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
for (size_t i = 0; i < mOutputs.size(); i++) {
desc = mOutputs.valueAt(i);
if (!desc->isDuplicated() && desc->supportsDevice(device)
&& desc->deviceSupportsEncodedFormats(deviceType)) {
&& desc->devicesSupportEncodedFormats({deviceType})) {
ALOGV("checkOutputsForDevice(): adding opened output %d on device %s",
mOutputs.keyAt(i), device->toString().c_str());
outputs.add(mOutputs.keyAt(i));
@ -4754,7 +4750,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
if (!desc->isDuplicated()) {
// exact match on device
if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
&& desc->deviceSupportsEncodedFormats(deviceType)) {
&& desc->devicesSupportEncodedFormats({deviceType})) {
outputs.add(mOutputs.keyAt(i));
} else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
@ -5025,7 +5021,7 @@ SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(
i, openOutputs.valueAt(i)->isDuplicated(),
openOutputs.valueAt(i)->supportedDevices().toString().c_str());
if (openOutputs.valueAt(i)->supportsAllDevices(devices)
&& openOutputs.valueAt(i)->deviceSupportsEncodedFormats(devices.types())) {
&& openOutputs.valueAt(i)->devicesSupportEncodedFormats(devices.types())) {
ALOGVV("%s() found output %d", __func__, openOutputs.keyAt(i));
outputs.add(openOutputs.keyAt(i));
}
@ -5160,9 +5156,8 @@ void AudioPolicyManager::checkA2dpSuspend()
}
bool isScoConnected =
((mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET &
~AUDIO_DEVICE_BIT_IN) != 0) ||
((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_ALL_SCO) != 0);
(mAvailableInputDevices.types().count(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0 ||
!Intersection(mAvailableOutputDevices.types(), getAudioDeviceOutAllScoSet()).empty());
// if suspended, restore A2DP output if:
// ((SCO device is NOT connected) ||
@ -5324,12 +5319,13 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre
}
/*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
and doesn't really need to.*/
DeviceVector speakerSafeDevices = devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER_SAFE);
DeviceVector speakerSafeDevices = devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER_SAFE);
if (!speakerSafeDevices.isEmpty()) {
devices.merge(mAvailableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
devices.merge(mAvailableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
devices.remove(speakerSafeDevices);
}
return devices.types();
// FIXME: use DeviceTypeSet when Java layer is ready for it.
return deviceTypesToBitMask(devices.types());
}
void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) {
@ -5389,7 +5385,7 @@ uint32_t AudioPolicyManager::setBeaconMute(bool mute) {
auto ttsVolumeSource = toVolumeSource(AUDIO_STREAM_TTS);
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, AUDIO_DEVICE_NONE);
setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, DeviceTypeSet());
const uint32_t latency = desc->latency() * 2;
if (latency > maxLatency) {
maxLatency = latency;
@ -5705,9 +5701,9 @@ sp<IOProfile> AudioPolicyManager::getInputProfile(const sp<DeviceDescriptor> &de
float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
VolumeSource volumeSource,
int index,
audio_devices_t device)
const DeviceTypeSet& deviceTypes)
{
float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(device), index);
float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(deviceTypes), index);
// handle the case of accessibility active while a ringtone is playing: if the ringtone is much
// louder than the accessibility prompt, the prompt cannot be heard, thus masking the touch
@ -5723,7 +5719,7 @@ float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
&& (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
mOutputs.isActive(ringVolumeSrc, 0)) {
auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, device);
const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, deviceTypes);
return ringVolumeDb - 4 > volumeDb ? ringVolumeDb - 4 : volumeDb;
}
@ -5738,9 +5734,9 @@ float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
volumeSource == toVolumeSource(AUDIO_STREAM_DTMF) ||
volumeSource == a11yVolumeSrc)) {
auto &voiceCurves = getVolumeCurves(callVolumeSrc);
int voiceVolumeIndex = voiceCurves.getVolumeIndex(device);
int voiceVolumeIndex = voiceCurves.getVolumeIndex(deviceTypes);
const float maxVoiceVolDb =
computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, device)
computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, deviceTypes)
+ IN_CALL_EARPIECE_HEADROOM_DB;
// FIXME: Workaround for call screening applications until a proper audio mode is defined
// to support this scenario : Exempt the RING stream from the audio cap if the audio was
@ -5766,9 +5762,10 @@ float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
// speaker is part of the select devices
// - if music is playing, always limit the volume to current music volume,
// with a minimum threshold at -36dB so that notification is always perceived.
if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
AUDIO_DEVICE_OUT_USB_HEADSET | AUDIO_DEVICE_OUT_HEARING_AID)) &&
if (!Intersection(deviceTypes,
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
AUDIO_DEVICE_OUT_USB_HEADSET, AUDIO_DEVICE_OUT_HEARING_AID}).empty() &&
((volumeSource == alarmVolumeSrc ||
volumeSource == ringVolumeSrc) ||
(volumeSource == toVolumeSource(AUDIO_STREAM_NOTIFICATION)) ||
@ -5783,31 +5780,33 @@ float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
mLimitRingtoneVolume) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
audio_devices_t musicDevice =
DeviceTypeSet musicDevice =
mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
nullptr, true /*fromCache*/).types();
auto &musicCurves = getVolumeCurves(AUDIO_STREAM_MUSIC);
float musicVolDb = computeVolume(musicCurves, musicVolumeSrc,
musicCurves.getVolumeIndex(musicDevice), musicDevice);
float musicVolDb = computeVolume(musicCurves,
musicVolumeSrc,
musicCurves.getVolumeIndex(musicDevice),
musicDevice);
float minVolDb = (musicVolDb > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
musicVolDb : SONIFICATION_HEADSET_VOLUME_MIN_DB;
if (volumeDb > minVolDb) {
volumeDb = minVolDb;
ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDb, musicVolDb);
}
if (device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES)) {
if (!Intersection(deviceTypes, {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}).empty()) {
// on A2DP, also ensure notification volume is not too low compared to media when
// intended to be played
if ((volumeDb > -96.0f) &&
(musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDb)) {
ALOGV("%s increasing volume for volume source=%d device=0x%X from %f to %f",
__func__, volumeSource, device, volumeDb,
ALOGV("%s increasing volume for volume source=%d device=%s from %f to %f",
__func__, volumeSource, dumpDeviceTypes(deviceTypes).c_str(), volumeDb,
musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
volumeDb = musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
}
}
} else if ((Volume::getDeviceForVolume(device) != AUDIO_DEVICE_OUT_SPEAKER) ||
} else if ((Volume::getDeviceForVolume(deviceTypes) != AUDIO_DEVICE_OUT_SPEAKER) ||
(!(volumeSource == alarmVolumeSrc || volumeSource == ringVolumeSrc))) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
}
@ -5846,7 +5845,7 @@ status_t AudioPolicyManager::checkAndSetVolume(IVolumeCurves &curves,
VolumeSource volumeSource,
int index,
const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
DeviceTypeSet deviceTypes,
int delayMs,
bool force)
{
@ -5872,17 +5871,20 @@ status_t AudioPolicyManager::checkAndSetVolume(IVolumeCurves &curves,
volumeSource, forceUseForComm);
return INVALID_OPERATION;
}
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->devices().types();
if (deviceTypes.empty()) {
deviceTypes = outputDesc->devices().types();
}
float volumeDb = computeVolume(curves, volumeSource, index, device);
if (outputDesc->isFixedVolume(device) ||
float volumeDb = computeVolume(curves, volumeSource, index, deviceTypes);
if (outputDesc->isFixedVolume(deviceTypes) ||
// Force VoIP volume to max for bluetooth SCO
((isVoiceVolSrc || isBtScoVolSrc) && (device & AUDIO_DEVICE_OUT_ALL_SCO) != 0)) {
((isVoiceVolSrc || isBtScoVolSrc) &&
isSingleDeviceType(deviceTypes, audio_is_bluetooth_out_sco_device))) {
volumeDb = 0.0f;
}
outputDesc->setVolume(volumeDb, volumeSource, curves.getStreamTypes(), device, delayMs, force);
outputDesc->setVolume(
volumeDb, volumeSource, curves.getStreamTypes(), deviceTypes, delayMs, force);
if (isVoiceVolSrc || isBtScoVolSrc) {
float voiceVolume;
@ -5901,15 +5903,16 @@ status_t AudioPolicyManager::checkAndSetVolume(IVolumeCurves &curves,
}
void AudioPolicyManager::applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
int delayMs,
bool force)
const DeviceTypeSet& deviceTypes,
int delayMs,
bool force)
{
ALOGVV("applyStreamVolumes() for device %08x", device);
for (const auto &volumeGroup : mEngine->getVolumeGroups()) {
auto &curves = getVolumeCurves(toVolumeSource(volumeGroup));
checkAndSetVolume(curves, toVolumeSource(volumeGroup),
curves.getVolumeIndex(device), outputDesc, device, delayMs, force);
curves.getVolumeIndex(deviceTypes),
outputDesc, deviceTypes, delayMs, force);
}
}
@ -5917,7 +5920,7 @@ void AudioPolicyManager::setStrategyMute(product_strategy_t strategy,
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs,
audio_devices_t device)
DeviceTypeSet deviceTypes)
{
std::vector<VolumeSource> sourcesToMute;
for (auto attributes: mEngine->getAllAttributesForProductStrategy(strategy)) {
@ -5929,7 +5932,7 @@ void AudioPolicyManager::setStrategyMute(product_strategy_t strategy,
}
}
for (auto source : sourcesToMute) {
setVolumeSourceMute(source, on, outputDesc, delayMs, device);
setVolumeSourceMute(source, on, outputDesc, delayMs, deviceTypes);
}
}
@ -5938,10 +5941,10 @@ void AudioPolicyManager::setVolumeSourceMute(VolumeSource volumeSource,
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs,
audio_devices_t device)
DeviceTypeSet deviceTypes)
{
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->devices().types();
if (deviceTypes.empty()) {
deviceTypes = outputDesc->devices().types();
}
auto &curves = getVolumeCurves(volumeSource);
if (on) {
@ -5950,7 +5953,7 @@ void AudioPolicyManager::setVolumeSourceMute(VolumeSource volumeSource,
(volumeSource != toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE) ||
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) ==
AUDIO_POLICY_FORCE_NONE))) {
checkAndSetVolume(curves, volumeSource, 0, outputDesc, device, delayMs);
checkAndSetVolume(curves, volumeSource, 0, outputDesc, deviceTypes, delayMs);
}
}
// increment mMuteCount after calling checkAndSetVolume() so that volume change is not
@ -5963,9 +5966,9 @@ void AudioPolicyManager::setVolumeSourceMute(VolumeSource volumeSource,
}
if (outputDesc->decMuteCount(volumeSource) == 0) {
checkAndSetVolume(curves, volumeSource,
curves.getVolumeIndex(device),
curves.getVolumeIndex(deviceTypes),
outputDesc,
device,
deviceTypes,
delayMs);
}
}

@ -176,7 +176,7 @@ public:
IVolumeCurves &volumeCurves);
status_t getVolumeIndex(const IVolumeCurves &curves, int &index,
audio_devices_t device) const;
const DeviceTypeSet& deviceTypes) const;
// return the strategy corresponding to a given stream type
virtual uint32_t getStrategyForStream(audio_stream_type_t stream)
@ -422,7 +422,7 @@ protected:
virtual float computeVolume(IVolumeCurves &curves,
VolumeSource volumeSource,
int index,
audio_devices_t device);
const DeviceTypeSet& deviceTypes);
// rescale volume index from srcStream within range of dstStream
int rescaleVolumeIndex(int srcIndex,
@ -432,12 +432,13 @@ protected:
virtual status_t checkAndSetVolume(IVolumeCurves &curves,
VolumeSource volumeSource, int index,
const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
DeviceTypeSet deviceTypes,
int delayMs = 0, bool force = false);
// apply all stream volumes to the specified output and device
void applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device, int delayMs = 0, bool force = false);
const DeviceTypeSet& deviceTypes,
int delayMs = 0, bool force = false);
/**
* @brief setStrategyMute Mute or unmute all active clients on the considered output
@ -452,7 +453,7 @@ protected:
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
audio_devices_t device = AUDIO_DEVICE_NONE);
DeviceTypeSet deviceTypes = DeviceTypeSet());
/**
* @brief setVolumeSourceMute Mute or unmute the volume source on the specified output
@ -467,7 +468,7 @@ protected:
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
audio_devices_t device = AUDIO_DEVICE_NONE);
DeviceTypeSet deviceTypes = DeviceTypeSet());
audio_mode_t getPhoneState();
@ -653,10 +654,6 @@ protected:
uint32_t updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs = 0);
sp<AudioPatch> createTelephonyPatch(bool isRx, const sp<DeviceDescriptor> &device,
uint32_t delayMs);
sp<DeviceDescriptor> findDevice(
const DeviceVector& devices, audio_devices_t device) const;
audio_devices_t getModuleDeviceTypes(
const DeviceVector& devices, const char *moduleId) const;
bool isDeviceOfModule(const sp<DeviceDescriptor>& devDesc, const char *moduleId) const;
status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,

Loading…
Cancel
Save