Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b2018b0 authored by François Gaffie's avatar François Gaffie Committed by Eric Laurent
Browse files

audiopolicy: add Volume Group introspection APIs



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

Test: make
Bug: 124767636
parent 63c0f36d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
../../media/libaudioclient/include/media/AudioVolumeGroup.h
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ cc_library_shared {
        "AudioAttributes.cpp",
        "AudioPolicy.cpp",
        "AudioProductStrategy.cpp",
        "AudioVolumeGroup.cpp",
    ],
    shared_libs: [
        "libaudioutils",
+26 −6
Original line number Diff line number Diff line
@@ -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);
}

// ---------------------------------------------------------------------------
+84 −0
Original line number Diff line number Diff line
/*
 * 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
+129 −20
Original line number Diff line number Diff line
@@ -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,7 +1087,9 @@ public:
            return status;
        }
        status = static_cast<status_t>(reply.readInt32());
        if (status == NO_ERROR) {
        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;
@@ -1097,23 +1101,76 @@ public:
            }
            strategies.push_back(strategy);
        }
        return NO_ERROR;
    }

    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 status;
        }
        status = remote()->transact(GET_STRATEGY_FOR_ATTRIBUTES, data, &reply);
        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 product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa)
    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 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());
        status = remote()->transact(GET_VOLUME_GROUP_FOR_ATTRIBUTES, data, &reply);
        if (status != NO_ERROR) {
            return status;
        }
        status = static_cast<status_t>(reply.readInt32());
        if (status != NO_ERROR) {
            return status;
        }
        return PRODUCT_STRATEGY_NONE;
        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);
    }
Loading