audiopolicy: add Volume Group introspection APIs

Change-Id: Ib02900bde69ee24685d9d374c0e5f73d33fa59e7
Signed-off-by: François Gaffie <francois.gaffie@renault.com>

Test: make
Bug: 124767636
gugelfrei
François Gaffie 6 years ago committed by Eric Laurent
parent 63c0f36d2b
commit 4b2018b0c0

@ -0,0 +1 @@
../../media/libaudioclient/include/media/AudioVolumeGroup.h

@ -10,6 +10,7 @@ cc_library_shared {
"AudioAttributes.cpp",
"AudioPolicy.cpp",
"AudioProductStrategy.cpp",
"AudioVolumeGroup.cpp",
],
shared_libs: [
"libaudioutils",

@ -1403,12 +1403,16 @@ audio_attributes_t AudioSystem::streamTypeToAttributes(audio_stream_type_t strea
audio_stream_type_t AudioSystem::attributesToStreamType(const audio_attributes_t &attr)
{
product_strategy_t strategyId =
AudioSystem::getProductStrategyFromAudioAttributes(AudioAttributes(attr));
product_strategy_t psId;
status_t ret = AudioSystem::getProductStrategyFromAudioAttributes(AudioAttributes(attr), psId);
if (ret != NO_ERROR) {
ALOGE("no strategy found for attributes %s", toString(attr).c_str());
return AUDIO_STREAM_MUSIC;
}
AudioProductStrategyVector strategies;
listAudioProductStrategies(strategies);
for (const auto &strategy : strategies) {
if (strategy.getId() == strategyId) {
if (strategy.getId() == psId) {
auto attrVect = strategy.getAudioAttributes();
auto iter = std::find_if(begin(attrVect), end(attrVect), [&attr](const auto &refAttr) {
return AudioProductStrategy::attributesMatches(
@ -1422,11 +1426,27 @@ audio_stream_type_t AudioSystem::attributesToStreamType(const audio_attributes_t
return AUDIO_STREAM_MUSIC;
}
product_strategy_t AudioSystem::getProductStrategyFromAudioAttributes(const AudioAttributes &aa)
status_t AudioSystem::getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
product_strategy_t &productStrategy)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PRODUCT_STRATEGY_NONE;
return aps->getProductStrategyFromAudioAttributes(aa);
if (aps == 0) return PERMISSION_DENIED;
return aps->getProductStrategyFromAudioAttributes(aa,productStrategy);
}
status_t AudioSystem::listAudioVolumeGroups(AudioVolumeGroupVector &groups)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->listAudioVolumeGroups(groups);
}
status_t AudioSystem::getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->getVolumeGroupFromAudioAttributes(aa, volumeGroup);
}
// ---------------------------------------------------------------------------

@ -0,0 +1,84 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "AudioVolumeGroup"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <media/AudioVolumeGroup.h>
#include <media/AudioAttributes.h>
namespace android {
status_t AudioVolumeGroup::readFromParcel(const Parcel *parcel)
{
status_t ret = parcel->readUtf8FromUtf16(&mName);
if (ret != NO_ERROR) {
return ret;
}
mGroupId = static_cast<volume_group_t>(parcel->readInt32());
size_t size = static_cast<size_t>(parcel->readInt32());
for (size_t i = 0; i < size; i++) {
AudioAttributes attribute;
attribute.readFromParcel(parcel);
if (ret != NO_ERROR) {
mAudioAttributes.clear();
return ret;
}
mAudioAttributes.push_back(attribute.getAttributes());
}
size = static_cast<size_t>(parcel->readInt32());
for (size_t i = 0; i < size; i++) {
audio_stream_type_t stream = static_cast<audio_stream_type_t>(parcel->readInt32());
mStreams.push_back(stream);
}
return NO_ERROR;
}
status_t AudioVolumeGroup::writeToParcel(Parcel *parcel) const
{
parcel->writeUtf8AsUtf16(mName);
parcel->writeInt32(static_cast<int32_t>(mGroupId));
size_t size = mAudioAttributes.size();
size_t sizePosition = parcel->dataPosition();
parcel->writeInt32(size);
size_t finalSize = size;
for (const auto &attributes : mAudioAttributes) {
size_t position = parcel->dataPosition();
AudioAttributes attribute(attributes);
status_t ret = attribute.writeToParcel(parcel);
if (ret != NO_ERROR) {
parcel->setDataPosition(position);
finalSize--;
}
}
if (size != finalSize) {
size_t position = parcel->dataPosition();
parcel->setDataPosition(sizePosition);
parcel->writeInt32(finalSize);
parcel->setDataPosition(position);
}
parcel->writeInt32(mStreams.size());
for (const auto &stream : mStreams) {
parcel->writeInt32(static_cast<int32_t>(stream));
}
return NO_ERROR;
}
} // namespace android

@ -95,6 +95,8 @@ enum {
GET_OFFLOAD_FORMATS_A2DP,
LIST_AUDIO_PRODUCT_STRATEGIES,
GET_STRATEGY_FOR_ATTRIBUTES,
LIST_AUDIO_VOLUME_GROUPS,
GET_VOLUME_GROUP_FOR_ATTRIBUTES
};
#define MAX_ITEMS_PER_LIST 1024
@ -1085,35 +1087,90 @@ public:
return status;
}
status = static_cast<status_t>(reply.readInt32());
if (status == NO_ERROR) {
uint32_t numStrategies = static_cast<uint32_t>(reply.readInt32());
for (size_t i = 0; i < numStrategies; i++) {
AudioProductStrategy strategy;
status = strategy.readFromParcel(&reply);
if (status != NO_ERROR) {
ALOGE("%s: failed to read strategies", __FUNCTION__);
strategies.clear();
return status;
}
strategies.push_back(strategy);
if (status != NO_ERROR) {
return status;
}
uint32_t numStrategies = static_cast<uint32_t>(reply.readInt32());
for (size_t i = 0; i < numStrategies; i++) {
AudioProductStrategy strategy;
status = strategy.readFromParcel(&reply);
if (status != NO_ERROR) {
ALOGE("%s: failed to read strategies", __FUNCTION__);
strategies.clear();
return status;
}
strategies.push_back(strategy);
}
return status;
return NO_ERROR;
}
virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa)
virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
product_strategy_t &productStrategy)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
status_t status = aa.writeToParcel(&data);
if (status != NO_ERROR) {
return PRODUCT_STRATEGY_NONE;
return status;
}
status = remote()->transact(GET_STRATEGY_FOR_ATTRIBUTES, data, &reply);
if (status == NO_ERROR) {
return static_cast<product_strategy_t>(reply.readInt32());
if (status != NO_ERROR) {
return status;
}
status = static_cast<status_t>(reply.readInt32());
if (status != NO_ERROR) {
return status;
}
productStrategy = static_cast<product_strategy_t>(reply.readInt32());
return NO_ERROR;
}
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
status_t status = remote()->transact(LIST_AUDIO_VOLUME_GROUPS, data, &reply);
if (status != NO_ERROR) {
return status;
}
status = static_cast<status_t>(reply.readInt32());
if (status != NO_ERROR) {
return status;
}
uint32_t numGroups = static_cast<uint32_t>(reply.readInt32());
for (size_t i = 0; i < numGroups; i++) {
AudioVolumeGroup group;
status = group.readFromParcel(&reply);
if (status != NO_ERROR) {
ALOGE("%s: failed to read volume groups", __FUNCTION__);
groups.clear();
return status;
}
groups.push_back(group);
}
return NO_ERROR;
}
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
status_t status = aa.writeToParcel(&data);
if (status != NO_ERROR) {
return status;
}
status = remote()->transact(GET_VOLUME_GROUP_FOR_ATTRIBUTES, data, &reply);
if (status != NO_ERROR) {
return status;
}
return PRODUCT_STRATEGY_NONE;
status = static_cast<status_t>(reply.readInt32());
if (status != NO_ERROR) {
return status;
}
volumeGroup = static_cast<volume_group_t>(reply.readInt32());
return NO_ERROR;
}
};
@ -1173,7 +1230,9 @@ status_t BnAudioPolicyService::onTransact(
case SET_A11Y_SERVICES_UIDS:
case SET_UID_DEVICE_AFFINITY:
case REMOVE_UID_DEVICE_AFFINITY:
case GET_OFFLOAD_FORMATS_A2DP: {
case GET_OFFLOAD_FORMATS_A2DP:
case LIST_AUDIO_VOLUME_GROUPS:
case GET_VOLUME_GROUP_FOR_ATTRIBUTES: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@ -1992,7 +2051,7 @@ status_t BnAudioPolicyService::onTransact(
status_t status = listAudioProductStrategies(strategies);
reply->writeInt32(status);
if (status != NO_ERROR) {
return status;
return NO_ERROR;
}
size_t size = strategies.size();
size_t sizePosition = reply->dataPosition();
@ -2021,11 +2080,61 @@ status_t BnAudioPolicyService::onTransact(
if (status != NO_ERROR) {
return status;
}
product_strategy_t strategy = getProductStrategyFromAudioAttributes(attributes);
product_strategy_t strategy;
status = getProductStrategyFromAudioAttributes(attributes, strategy);
reply->writeInt32(status);
if (status != NO_ERROR) {
return NO_ERROR;
}
reply->writeUint32(static_cast<int>(strategy));
return NO_ERROR;
}
case LIST_AUDIO_VOLUME_GROUPS: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
AudioVolumeGroupVector groups;
status_t status = listAudioVolumeGroups(groups);
reply->writeInt32(status);
if (status != NO_ERROR) {
return NO_ERROR;
}
size_t size = groups.size();
size_t sizePosition = reply->dataPosition();
reply->writeInt32(size);
size_t finalSize = size;
for (size_t i = 0; i < size; i++) {
size_t position = reply->dataPosition();
if (groups[i].writeToParcel(reply) != NO_ERROR) {
reply->setDataPosition(position);
finalSize--;
}
}
if (size != finalSize) {
size_t position = reply->dataPosition();
reply->setDataPosition(sizePosition);
reply->writeInt32(finalSize);
reply->setDataPosition(position);
}
return NO_ERROR;
}
case GET_VOLUME_GROUP_FOR_ATTRIBUTES: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
AudioAttributes attributes;
status_t status = attributes.readFromParcel(&data);
if (status != NO_ERROR) {
return status;
}
volume_group_t group;
status = getVolumeGroupFromAudioAttributes(attributes, group);
reply->writeInt32(status);
if (status != NO_ERROR) {
return NO_ERROR;
}
reply->writeUint32(static_cast<int>(group));
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}

@ -21,6 +21,7 @@
#include <media/AudioPolicy.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
#include <media/AudioIoDescriptor.h>
#include <media/IAudioFlingerClient.h>
#include <media/IAudioPolicyServiceClient.h>
@ -367,11 +368,17 @@ public:
static bool isHapticPlaybackSupported();
static status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
static product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa);
static status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
product_strategy_t &productStrategy);
static audio_attributes_t streamTypeToAttributes(audio_stream_type_t stream);
static audio_stream_type_t attributesToStreamType(const audio_attributes_t &attr);
static status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups);
static status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup);
// ----------------------------------------------------------------------------
class AudioPortCallback : public RefBase

@ -0,0 +1,54 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <media/AudioProductStrategy.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <binder/Parcelable.h>
namespace android {
class AudioVolumeGroup : public Parcelable
{
public:
AudioVolumeGroup() {}
AudioVolumeGroup(const std::string &name,
volume_group_t group,
const AttributesVector &attributes,
const StreamTypeVector &streams) :
mName(name), mGroupId(group), mAudioAttributes(attributes), mStreams(streams) {}
const std::string &getName() const { return mName; }
volume_group_t getId() const { return mGroupId; }
AttributesVector getAudioAttributes() const { return mAudioAttributes; }
StreamTypeVector getStreamTypes() const { return mStreams; }
status_t readFromParcel(const Parcel *parcel) override;
status_t writeToParcel(Parcel *parcel) const override;
private:
std::string mName;
volume_group_t mGroupId = VOLUME_GROUP_NONE;
AttributesVector mAudioAttributes;
StreamTypeVector mStreams;
};
using AudioVolumeGroupVector = std::vector<AudioVolumeGroup>;
} // namespace android

@ -198,7 +198,12 @@ public:
virtual bool isHapticPlaybackSupported() = 0;
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa) = 0;
virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
product_strategy_t &productStrategy) = 0;
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup) = 0;
};

@ -244,7 +244,13 @@ public:
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa) = 0;
virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
product_strategy_t &productStrategy) = 0;
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup) = 0;
};

@ -88,6 +88,8 @@ public:
AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const override;
status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const override;
void dump(String8 *dst) const override;

@ -274,6 +274,15 @@ AttributesVector EngineBase::getAllAttributesForVolumeGroup(volume_group_t volum
mVolumeGroups.at(volumeGroup)->getSupportedAttributes() : AttributesVector();
}
status_t EngineBase::listAudioVolumeGroups(AudioVolumeGroupVector &groups) const
{
for (const auto &iter : mVolumeGroups) {
groups.push_back({iter.second->getName(), iter.second->getId(),
iter.second->getSupportedAttributes(), iter.second->getStreamTypes()});
}
return NO_ERROR;
}
void EngineBase::dump(String8 *dst) const
{
mProductStrategies.dump(dst, 2);

@ -18,6 +18,7 @@
#include <AudioPolicyManagerObserver.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
#include <IVolumeCurves.h>
#include <policy.h>
#include <Volume.h>
@ -286,6 +287,15 @@ public:
virtual AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const = 0;
/**
* @brief listAudioVolumeGroups introspection API to get the Audio Volume Groups, aka
* former stream aliases in Audio Service, defining volume curves attached to one or more
* Audio Attributes.
* @param groups
* @return NO_ERROR if the volume groups were retrieved successfully, error code otherwise
*/
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const = 0;
virtual void dump(String8 *dst) const = 0;
protected:

@ -268,9 +268,23 @@ public:
return mEngine->listAudioProductStrategies(strategies);
}
virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa)
virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
product_strategy_t &productStrategy)
{
return mEngine->getProductStrategyForAttributes(aa.getAttributes());
productStrategy = mEngine->getProductStrategyForAttributes(aa.getAttributes());
return productStrategy != PRODUCT_STRATEGY_NONE ? NO_ERROR : BAD_VALUE;
}
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups)
{
return mEngine->listAudioVolumeGroups(groups);
}
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup)
{
volumeGroup = mEngine->getVolumeGroupForAttributes(aa.getAttributes());
return volumeGroup != VOLUME_GROUP_NONE ? NO_ERROR : BAD_VALUE;
}
protected:

@ -1204,13 +1204,32 @@ status_t AudioPolicyService::listAudioProductStrategies(AudioProductStrategyVect
return mAudioPolicyManager->listAudioProductStrategies(strategies);
}
product_strategy_t AudioPolicyService::getProductStrategyFromAudioAttributes(
const AudioAttributes &aa)
status_t AudioPolicyService::getProductStrategyFromAudioAttributes(
const AudioAttributes &aa, product_strategy_t &productStrategy)
{
if (mAudioPolicyManager == NULL) {
return PRODUCT_STRATEGY_NONE;
return NO_INIT;
}
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->getProductStrategyFromAudioAttributes(aa, productStrategy);
}
status_t AudioPolicyService::listAudioVolumeGroups(AudioVolumeGroupVector &groups)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->listAudioVolumeGroups(groups);
}
status_t AudioPolicyService::getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->getProductStrategyFromAudioAttributes(aa);
return mAudioPolicyManager->getVolumeGroupFromAudioAttributes(aa, volumeGroup);
}
} // namespace android

@ -231,7 +231,13 @@ public:
virtual bool isHapticPlaybackSupported();
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa);
virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
product_strategy_t &productStrategy);
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups);
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup);
status_t doStopOutput(audio_port_handle_t portId);
void doReleaseOutput(audio_port_handle_t portId);

Loading…
Cancel
Save