Merge "Add getDirectProfilesForAttributes"
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index b3c82787..86139c7 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2314,6 +2314,28 @@
return NO_ERROR;
}
+status_t AudioSystem::getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ std::vector<audio_profile>* audioProfiles) {
+ if (attr == nullptr) {
+ return BAD_VALUE;
+ }
+
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) {
+ return PERMISSION_DENIED;
+ }
+
+ media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+
+ std::vector<media::audio::common::AudioProfile> audioProfilesAidl;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ aps->getDirectProfilesForAttributes(attrAidl, &audioProfilesAidl)));
+ *audioProfiles = VALUE_OR_RETURN_STATUS(convertContainer<std::vector<audio_profile>>(
+ audioProfilesAidl, aidl2legacy_AudioProfile_audio_profile, false /*isInput*/));
+
+ return NO_ERROR;
+}
class CaptureStateListenerImpl : public media::BnCaptureStateListener,
public IBinder::DeathRecipient {
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 7895ae3..b1a9d94 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -48,6 +48,7 @@
import android.media.audio.common.AudioDeviceDescription;
import android.media.audio.common.AudioFormatDescription;
import android.media.audio.common.AudioMode;
+import android.media.audio.common.AudioProfile;
import android.media.audio.common.AudioOffloadInfo;
import android.media.audio.common.AudioSource;
import android.media.audio.common.AudioStreamType;
@@ -381,6 +382,12 @@
/**
* Query how the direct playback is currently supported on the device.
*/
- AudioDirectMode getDirectPlaybackSupport(in AudioAttributesInternal attr,
+ AudioDirectMode getDirectPlaybackSupport(in AudioAttributesInternal attr,
in AudioConfig config);
+
+ /**
+ * Query audio profiles available for direct playback on the current output device(s)
+ * for the specified audio attributes.
+ */
+ AudioProfile[] getDirectProfilesForAttributes(in AudioAttributesInternal attr);
}
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/libaudioclient/include/media/AidlConversionUtil.h
index dfabd55..227d823 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/libaudioclient/include/media/AidlConversionUtil.h
@@ -123,6 +123,21 @@
}
/**
+ * A generic template that helps convert containers of convertible types
+ * using an item conversion function with an additional parameter.
+ */
+template<typename OutputContainer, typename InputContainer, typename Func, typename Parameter>
+ConversionResult<OutputContainer>
+convertContainer(const InputContainer& input, const Func& itemConversion, const Parameter& param) {
+ OutputContainer output;
+ auto ins = std::inserter(output, output.begin());
+ for (const auto& item : input) {
+ *ins = VALUE_OR_RETURN(itemConversion(item, param));
+ }
+ return output;
+}
+
+/**
* A generic template that helps to "zip" two input containers of the same size
* into a single vector of converted types. The conversion function must
* thus accept two arguments.
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 11eb070..09127fb 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -550,6 +550,16 @@
audio_direct_mode_t *directMode);
+ /**
+ * Query which direct audio profiles are available for the specified audio attributes.
+ * @param attr audio attributes describing the playback use case
+ * @param audioProfiles out: a vector of audio profiles
+ * @return NO_ERROR in case of success, DEAD_OBJECT, NO_INIT, BAD_VALUE, PERMISSION_DENIED
+ * in case of error.
+ */
+ static status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ std::vector<audio_profile>* audioProfiles);
+
// A listener for capture state changes.
class CaptureStateListener : public virtual RefBase {
public:
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 9a67bb7..734fa9c 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -154,6 +154,26 @@
ConversionResult<AudioProfile::Aidl>
AudioProfile::toParcelable(bool isInput) const {
+ media::audio::common::AudioProfile parcelable = VALUE_OR_RETURN(toCommonParcelable(isInput));
+ media::AudioProfileSys parcelableSys;
+ parcelableSys.isDynamicFormat = mIsDynamicFormat;
+ parcelableSys.isDynamicChannels = mIsDynamicChannels;
+ parcelableSys.isDynamicRate = mIsDynamicRate;
+ return std::make_pair(parcelable, parcelableSys);
+}
+
+ConversionResult<sp<AudioProfile>> AudioProfile::fromParcelable(
+ const AudioProfile::Aidl& aidl, bool isInput) {
+ sp<AudioProfile> legacy = VALUE_OR_RETURN(fromCommonParcelable(aidl.first, isInput));
+ const auto& parcelableSys = aidl.second;
+ legacy->mIsDynamicFormat = parcelableSys.isDynamicFormat;
+ legacy->mIsDynamicChannels = parcelableSys.isDynamicChannels;
+ legacy->mIsDynamicRate = parcelableSys.isDynamicRate;
+ return legacy;
+}
+
+ConversionResult<media::audio::common::AudioProfile>
+AudioProfile::toCommonParcelable(bool isInput) const {
media::audio::common::AudioProfile parcelable;
parcelable.name = mName;
parcelable.format = VALUE_OR_RETURN(
@@ -164,44 +184,35 @@
// of using 'legacy2aidl_audio_profile_AudioProfile' from AidlConversion.
parcelable.channelMasks = VALUE_OR_RETURN(
convertContainer<std::vector<AudioChannelLayout>>(
- mChannelMasks,
- [isInput](audio_channel_mask_t m) {
- return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
- }));
+ mChannelMasks,
+ [isInput](audio_channel_mask_t m) {
+ return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
+ }));
parcelable.sampleRates = VALUE_OR_RETURN(
convertContainer<std::vector<int32_t>>(mSamplingRates,
convertIntegral<int32_t, uint32_t>));
parcelable.encapsulationType = VALUE_OR_RETURN(
legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(mEncapsulationType));
- media::AudioProfileSys parcelableSys;
- parcelableSys.isDynamicFormat = mIsDynamicFormat;
- parcelableSys.isDynamicChannels = mIsDynamicChannels;
- parcelableSys.isDynamicRate = mIsDynamicRate;
- return std::make_pair(parcelable, parcelableSys);
+ return parcelable;
}
-ConversionResult<sp<AudioProfile>> AudioProfile::fromParcelable(
- const AudioProfile::Aidl& aidl, bool isInput) {
+ConversionResult<sp<AudioProfile>> AudioProfile::fromCommonParcelable(
+ const media::audio::common::AudioProfile& aidl, bool isInput) {
sp<AudioProfile> legacy = new AudioProfile();
- const auto& parcelable = aidl.first;
- legacy->mName = parcelable.name;
+ legacy->mName = aidl.name;
legacy->mFormat = VALUE_OR_RETURN(
- aidl2legacy_AudioFormatDescription_audio_format_t(parcelable.format));
+ aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
legacy->mChannelMasks = VALUE_OR_RETURN(
- convertContainer<ChannelMaskSet>(parcelable.channelMasks,
- [isInput](const AudioChannelLayout& l) {
- return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
- }));
+ convertContainer<ChannelMaskSet>(aidl.channelMasks,
+ [isInput](const AudioChannelLayout& l) {
+ return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
+ }));
legacy->mSamplingRates = VALUE_OR_RETURN(
- convertContainer<SampleRateSet>(parcelable.sampleRates,
+ convertContainer<SampleRateSet>(aidl.sampleRates,
convertIntegral<uint32_t, int32_t>));
legacy->mEncapsulationType = VALUE_OR_RETURN(
aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
- parcelable.encapsulationType));
- const auto& parcelableSys = aidl.second;
- legacy->mIsDynamicFormat = parcelableSys.isDynamicFormat;
- legacy->mIsDynamicChannels = parcelableSys.isDynamicChannels;
- legacy->mIsDynamicRate = parcelableSys.isDynamicRate;
+ aidl.encapsulationType));
return legacy;
}
@@ -215,6 +226,16 @@
return legacy->toParcelable(isInput);
}
+ConversionResult<sp<AudioProfile>>
+aidl2legacy_AudioProfile_common(const media::audio::common::AudioProfile& aidl, bool isInput) {
+ return AudioProfile::fromCommonParcelable(aidl, isInput);
+}
+
+ConversionResult<media::audio::common::AudioProfile>
+legacy2aidl_AudioProfile_common(const sp<AudioProfile>& legacy, bool isInput) {
+ return legacy->toCommonParcelable(isInput);
+}
+
ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
{
ssize_t index = size();
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index d7cddb7..c3a0fb2 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -85,6 +85,11 @@
static ConversionResult<sp<AudioProfile>> fromParcelable(
const Aidl& aidl, bool isInput);
+ ConversionResult<media::audio::common::AudioProfile>
+ toCommonParcelable(bool isInput) const;
+ static ConversionResult<sp<AudioProfile>> fromCommonParcelable(
+ const media::audio::common::AudioProfile& aidl, bool isInput);
+
private:
std::string mName;
@@ -108,6 +113,11 @@
ConversionResult<AudioProfile::Aidl>
legacy2aidl_AudioProfile(const sp<AudioProfile>& legacy, bool isInput);
+ConversionResult<sp<AudioProfile>>
+aidl2legacy_AudioProfile_common(const media::audio::common::AudioProfile& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioProfile>
+legacy2aidl_AudioProfile_common(const sp<AudioProfile>& legacy, bool isInput);
+
class AudioProfileVector : public std::vector<sp<AudioProfile>>
{
public:
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index f6f3b9a..ea958f5 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -404,8 +404,11 @@
*/
virtual audio_direct_mode_t getDirectPlaybackSupport(const audio_attributes_t *attr,
const audio_config_t *config) = 0;
-};
+ // retrieves the list of available direct audio profiles for the given audio attributes
+ virtual status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ AudioProfileVector& audioProfiles) = 0;
+};
// Audio Policy client Interface
class AudioPolicyClientInterface
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 654e4bf..dff36e2 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -30,6 +30,7 @@
#include <libxml/parser.h>
#include <libxml/xinclude.h>
#include <media/AudioPolicy.h>
+#include <media/AudioProfile.h>
#include <media/PatchBuilder.h>
#include <media/RecordingActivityTracker.h>
@@ -842,6 +843,7 @@
void process() override;
void fuzzGetDirectPlaybackSupport();
+ void fuzzGetDirectProfilesForAttributes();
protected:
void setDeviceConnectionState();
@@ -909,11 +911,25 @@
}
}
+void AudioPolicyManagerFuzzerDeviceConnection::fuzzGetDirectProfilesForAttributes() {
+ const uint32_t numTestCases = mFdp->ConsumeIntegralInRange<uint32_t>(1, 10);
+ for (int i = 0; i < numTestCases; ++i) {
+ AudioProfileVector audioProfiles;
+ audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+ attr.content_type = getValueFromVector<audio_content_type_t>(mFdp, kAudioContentTypes);
+ attr.usage = getValueFromVector<audio_usage_t>(mFdp, kAudioUsages);
+ attr.source = getValueFromVector<audio_source_t>(mFdp, kAudioSources);
+ attr.flags = getValueFromVector<audio_flags_mask_t>(mFdp, kAudioFlagMasks);
+ mManager->getDirectProfilesForAttributes(&attr, audioProfiles);
+ }
+}
+
void AudioPolicyManagerFuzzerDeviceConnection::process() {
if (initialize()) {
setDeviceConnectionState();
explicitlyRoutingAfterConnection();
fuzzGetDirectPlaybackSupport();
+ fuzzGetDirectProfilesForAttributes();
fuzzPatchCreation();
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ee2c0f7..48176da 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3833,6 +3833,47 @@
return directMode;
}
+status_t AudioPolicyManager::getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ AudioProfileVector& audioProfilesVector) {
+ AudioDeviceTypeAddrVector devices;
+ status_t status = getDevicesForAttributes(*attr, &devices);
+ if (status != OK) {
+ return status;
+ }
+ ALOGV("%s: found %zu output devices for attributes.", __func__, devices.size());
+ if (devices.empty()) {
+ return OK; // no output devices for the attributes
+ }
+
+ for (const auto& hwModule : mHwModules) {
+ for (const auto& curProfile : hwModule->getOutputProfiles()) {
+ if (!curProfile->asAudioPort()->isDirectOutput()) {
+ continue;
+ }
+ // Allow only profiles that support all the available and routed devices
+ DeviceVector supportedDevices = curProfile->getSupportedDevices();
+ if (supportedDevices.getDevicesFromDeviceTypeAddrVec(devices).size()
+ != devices.size()) {
+ continue;
+ }
+
+ const auto audioProfiles = curProfile->asAudioPort()->getAudioProfiles();
+ ALOGV("%s: found direct profile (%s) with %zu audio profiles.",
+ __func__, curProfile->getTagName().c_str(), audioProfiles.size());
+ for (const auto& audioProfile : audioProfiles) {
+ if (audioProfile->isValid() && !audioProfilesVector.contains(audioProfile)
+ // TODO - why do we have same PCM format with both dynamic and non dynamic format
+ && audioProfile->isDynamicFormat()) {
+ ALOGV("%s: adding audio profile with encoding (%d).",
+ __func__, audioProfile->getFormat());
+ audioProfilesVector.add(audioProfile);
+ }
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
@@ -6305,6 +6346,7 @@
return devices.types();
}
+// TODO - consider MSD routes b/214971780
status_t AudioPolicyManager::getDevicesForAttributes(
const audio_attributes_t &attr, AudioDeviceTypeAddrVector *devices) {
if (devices == nullptr) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index dd69295..b4fc4d4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -371,6 +371,9 @@
virtual audio_direct_mode_t getDirectPlaybackSupport(const audio_attributes_t *attr,
const audio_config_t *config);
+ virtual status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ AudioProfileVector& audioProfiles);
+
bool isCallScreenModeSupported() override;
void onNewAudioModulesAvailable() override;
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index a30768a..3929e55 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -2372,4 +2372,24 @@
return Status::ok();
}
+Status AudioPolicyService::getDirectProfilesForAttributes(
+ const media::AudioAttributesInternal& attrAidl,
+ std::vector<media::audio::common::AudioProfile>* _aidl_return) {
+ if (mAudioPolicyManager == nullptr) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+ audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ AudioProfileVector audioProfiles;
+
+ Mutex::Autolock _l(mLock);
+ RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
+ mAudioPolicyManager->getDirectProfilesForAttributes(&attr, audioProfiles)));
+ *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
+ convertContainer<std::vector<media::audio::common::AudioProfile>>(
+ audioProfiles, legacy2aidl_AudioProfile_common, false /*isInput*/));
+
+ return Status::ok();
+}
+
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 84b1e50..ba28857 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -276,6 +276,9 @@
const AudioConfig& config,
media::AudioDirectMode* _aidl_return) override;
+ binder::Status getDirectProfilesForAttributes(const media::AudioAttributesInternal& attr,
+ std::vector<media::audio::common::AudioProfile>* _aidl_return) override;
+
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
// IBinder::DeathRecipient
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 9d0d558..ff06937 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -34,6 +34,7 @@
using AudioPolicyManager::setMsdOutputPatches;
using AudioPolicyManager::getAudioPatches;
using AudioPolicyManager::getDirectPlaybackSupport;
+ using AudioPolicyManager::getDirectProfilesForAttributes;
uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
};