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

Commit 04e31553 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Allow to set/get/remove disabled devices for strategy/capture preset." into sc-dev

parents 3e0ed6a0 2336de89
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -170,11 +170,13 @@ private:
    status_t getMediaDevicesForRole(device_role_t role, const DeviceVector& availableDevices,
            DeviceVector& devices) const;

    void dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const;

    AudioPolicyManagerObserver *mApmObserver = nullptr;

    ProductStrategyMap mProductStrategies;
    ProductStrategyPreferredRoutingMap mProductStrategyPreferredDevices;
    CapturePresetDevicesRoleMap mCapturePresetDevicesRole;
    ProductStrategyDevicesRoleMap mProductStrategyDeviceRoleMap;
    CapturePresetDevicesRoleMap mCapturePresetDevicesRoleMap;
    VolumeGroupMap mVolumeGroups;
    LastRemovableMediaDevices mLastRemovableMediaDevices;
    audio_mode_t mPhoneState = AUDIO_MODE_NORMAL;  /**< current phone state. */
+15 −14
Original line number Diff line number Diff line
@@ -18,20 +18,20 @@

#include "VolumeGroup.h"

#include <system/audio.h>
#include <utils/RefBase.h>
#include <HandleGenerator.h>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include <map>
#include <utils/Errors.h>
#include <utils/String8.h>

#include <HandleGenerator.h>
#include <media/AudioAttributes.h>
#include <media/AudioContainers.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>

#include <vector>
#include <system/audio.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/String8.h>

namespace android {

@@ -170,11 +170,12 @@ private:
    product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
};

class ProductStrategyPreferredRoutingMap : public std::map<product_strategy_t,
                                                           AudioDeviceTypeAddrVector>
{
public:
    void dump(String8 *dst, int spaces = 0) const;
};
using ProductStrategyDevicesRoleMap =
        std::map<std::pair<product_strategy_t, device_role_t>, AudioDeviceTypeAddrVector>;

void dumpProductStrategyDevicesRoleMap(
        const ProductStrategyDevicesRoleMap& productStrategyDeviceRoleMap,
        String8 *dst,
        int spaces);

} // namespace android
+125 −133
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#define LOG_TAG "APM::AudioPolicyEngine/Base"
//#define LOG_NDEBUG 0

#include <functional>
#include <string>
#include <sys/stat.h>

#include "EngineBase.h"
@@ -349,23 +351,33 @@ status_t EngineBase::listAudioVolumeGroups(AudioVolumeGroupVector &groups) const
    return NO_ERROR;
}

status_t EngineBase::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
            const AudioDeviceTypeAddrVector &devices)
{
    // verify strategy exists
    if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
        ALOGE("%s invalid strategy %u", __func__, strategy);
namespace {
template <typename T>
status_t setDevicesRoleForT(
        std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
        T t, device_role_t role, const AudioDeviceTypeAddrVector &devices,
        const std::string& logStr, std::function<bool(T)> p) {
    if (!p(t)) {
        ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
        return BAD_VALUE;
    }

    switch (role) {
    case DEVICE_ROLE_PREFERRED:
        mProductStrategyPreferredDevices[strategy] = devices;
        break;
    case DEVICE_ROLE_DISABLED:
        // TODO (b/184065221): support set devices role as disabled for strategy.
        ALOGI("%s no implemented for role as %d", __func__, role);
        break;
    case DEVICE_ROLE_DISABLED: {
        tDevicesRoleMap[std::make_pair(t, role)] = devices;
        // The preferred devices and disabled devices are mutually exclusive. Once a device is added
        // the a list, it must be removed from the other one.
        const device_role_t roleToRemove = role == DEVICE_ROLE_PREFERRED ? DEVICE_ROLE_DISABLED
                                                                         : DEVICE_ROLE_PREFERRED;
        auto it = tDevicesRoleMap.find(std::make_pair(t, roleToRemove));
        if (it != tDevicesRoleMap.end()) {
            it->second = excludeDeviceTypeAddrsFrom(it->second, devices);
            if (it->second.empty()) {
                tDevicesRoleMap.erase(it);
            }
        }
    } break;
    case DEVICE_ROLE_NONE:
        // Intentionally fall-through as it is no need to set device role as none for a strategy.
    default:
@@ -375,28 +387,26 @@ status_t EngineBase::setDevicesRoleForStrategy(product_strategy_t strategy, devi
    return NO_ERROR;
}

status_t EngineBase::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
{
    // verify strategy exists
    if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
        ALOGE("%s invalid strategy %u", __func__, strategy);
template <typename T>
status_t removeAllDevicesRoleForT(
        std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
        T t, device_role_t role, const std::string& logStr, std::function<bool(T)> p) {
    if (!p(t)) {
        ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
        return BAD_VALUE;
    }

    switch (role) {
    case DEVICE_ROLE_PREFERRED:
        if (mProductStrategyPreferredDevices.erase(strategy) == 0) {
            // no preferred device was set
    case DEVICE_ROLE_DISABLED:
        if (tDevicesRoleMap.erase(std::make_pair(t, role)) == 0) {
            // no preferred/disabled device was set
            return NAME_NOT_FOUND;
        }
        break;
    case DEVICE_ROLE_DISABLED:
        // TODO (b/184065221): support remove devices role as disabled for strategy.
        ALOGI("%s no implemented for role as %d", __func__, role);
        break;
    case DEVICE_ROLE_NONE:
        // Intentionally fall-through as it makes no sense to remove devices with
        // role as DEVICE_ROLE_NONE for a strategy
        // role as DEVICE_ROLE_NONE
    default:
        ALOGE("%s invalid role %d", __func__, role);
        return BAD_VALUE;
@@ -404,30 +414,27 @@ status_t EngineBase::removeDevicesRoleForStrategy(product_strategy_t strategy, d
    return NO_ERROR;
}

status_t EngineBase::getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
            AudioDeviceTypeAddrVector &devices) const
{
    // verify strategy exists
    if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
        ALOGE("%s unknown strategy %u", __func__, strategy);
template <typename T>
status_t getDevicesRoleForT(
        const std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
        T t, device_role_t role, AudioDeviceTypeAddrVector &devices, const std::string& logStr,
        std::function<bool(T)> p) {
    if (!p(t)) {
        ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
        return BAD_VALUE;
    }

    switch (role) {
    case DEVICE_ROLE_PREFERRED: {
        // preferred device for this strategy?
        auto devIt = mProductStrategyPreferredDevices.find(strategy);
        if (devIt == mProductStrategyPreferredDevices.end()) {
            ALOGV("%s no preferred device for strategy %u", __func__, strategy);
    case DEVICE_ROLE_PREFERRED:
    case DEVICE_ROLE_DISABLED: {
        auto it = tDevicesRoleMap.find(std::make_pair(t, role));
        if (it == tDevicesRoleMap.end()) {
            ALOGV("%s no device as role %u for %s %u", __func__, role, logStr.c_str(), t);
            return NAME_NOT_FOUND;
        }

        devices = devIt->second;
        devices = it->second;
    } break;
    case DEVICE_ROLE_DISABLED:
        // TODO (b/184065221): support devices role as disabled for strategy.
        ALOGV("%s no implemented for role as %d", __func__, role);
        break;
    case DEVICE_ROLE_NONE:
        // Intentionally fall-through as the DEVICE_ROLE_NONE is never set
    default:
@@ -437,32 +444,45 @@ status_t EngineBase::getDevicesForRoleAndStrategy(product_strategy_t strategy, d
    return NO_ERROR;
}

status_t EngineBase::setDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
} // namespace

status_t EngineBase::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
            const AudioDeviceTypeAddrVector &devices)
{
    // verify if the audio source is valid
    if (!audio_is_valid_audio_source(audioSource)) {
        ALOGE("%s unknown audio source %u", __func__, audioSource);
    std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
        return mProductStrategies.find(strategy) != mProductStrategies.end();
    };
    return setDevicesRoleForT(
            mProductStrategyDeviceRoleMap, strategy, role, devices, "strategy" /*logStr*/, p);
}

    switch (role) {
    case DEVICE_ROLE_PREFERRED:
        mCapturePresetDevicesRole[audioSource][role] = devices;
        // When the devices are set as preferred devices, remove them from the disabled devices.
        doRemoveDevicesRoleForCapturePreset(
                audioSource, DEVICE_ROLE_DISABLED, devices, false /*forceMatched*/);
        break;
    case DEVICE_ROLE_DISABLED:
        // TODO: support setting devices role as disabled for capture preset.
        ALOGI("%s no implemented for role as %d", __func__, role);
        break;
    case DEVICE_ROLE_NONE:
        // Intentionally fall-through as it is no need to set device role as none
    default:
        ALOGE("%s invalid role %d", __func__, role);
        return BAD_VALUE;
status_t EngineBase::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
{
    std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
        return mProductStrategies.find(strategy) != mProductStrategies.end();
    };
    return removeAllDevicesRoleForT(
            mProductStrategyDeviceRoleMap, strategy, role, "strategy" /*logStr*/, p);
}
    return NO_ERROR;

status_t EngineBase::getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
            AudioDeviceTypeAddrVector &devices) const
{
    std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
        return mProductStrategies.find(strategy) != mProductStrategies.end();
    };
    return getDevicesRoleForT(
            mProductStrategyDeviceRoleMap, strategy, role, devices, "strategy" /*logStr*/, p);
}

status_t EngineBase::setDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
        const AudioDeviceTypeAddrVector &devices)
{
    std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
        return audio_is_valid_audio_source(audioSource);
    };
    return setDevicesRoleForT(
            mCapturePresetDevicesRoleMap, audioSource, role, devices, "audio source" /*logStr*/, p);
}

status_t EngineBase::addDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
@@ -475,19 +495,20 @@ status_t EngineBase::addDevicesRoleForCapturePreset(audio_source_t audioSource,

    switch (role) {
    case DEVICE_ROLE_PREFERRED:
        mCapturePresetDevicesRole[audioSource][role] = excludeDeviceTypeAddrsFrom(
                mCapturePresetDevicesRole[audioSource][role], devices);
    case DEVICE_ROLE_DISABLED: {
        const auto audioSourceRole = std::make_pair(audioSource, role);
        mCapturePresetDevicesRoleMap[audioSourceRole] = excludeDeviceTypeAddrsFrom(
                mCapturePresetDevicesRoleMap[audioSourceRole], devices);
        for (const auto &device : devices) {
            mCapturePresetDevicesRole[audioSource][role].push_back(device);
            mCapturePresetDevicesRoleMap[audioSourceRole].push_back(device);
        }
        // When the devices are set as preferred devices, remove them from the disabled devices.
        doRemoveDevicesRoleForCapturePreset(
                audioSource, DEVICE_ROLE_DISABLED, devices, false /*forceMatched*/);
        break;
    case DEVICE_ROLE_DISABLED:
        // TODO: support setting devices role as disabled for capture preset.
        ALOGI("%s no implemented for role as %d", __func__, role);
        break;
                audioSource,
                role == DEVICE_ROLE_PREFERRED ? DEVICE_ROLE_DISABLED : DEVICE_ROLE_PREFERRED,
                devices,
                false /*forceMatched*/);
    } break;
    case DEVICE_ROLE_NONE:
        // Intentionally fall-through as it is no need to set device role as none
    default:
@@ -513,21 +534,22 @@ status_t EngineBase::doRemoveDevicesRoleForCapturePreset(audio_source_t audioSou
    switch (role) {
    case DEVICE_ROLE_PREFERRED:
    case DEVICE_ROLE_DISABLED: {
        if (mCapturePresetDevicesRole.count(audioSource) == 0 ||
                mCapturePresetDevicesRole[audioSource].count(role) == 0) {
        const auto audioSourceRole = std::make_pair(audioSource, role);
        if (mCapturePresetDevicesRoleMap.find(audioSourceRole) ==
                mCapturePresetDevicesRoleMap.end()) {
            return NAME_NOT_FOUND;
        }
        AudioDeviceTypeAddrVector remainingDevices = excludeDeviceTypeAddrsFrom(
                mCapturePresetDevicesRole[audioSource][role], devices);
                mCapturePresetDevicesRoleMap[audioSourceRole], devices);
        if (forceMatched && remainingDevices.size() !=
                mCapturePresetDevicesRole[audioSource][role].size() - devices.size()) {
                mCapturePresetDevicesRoleMap[audioSourceRole].size() - devices.size()) {
            // There are some devices from `devicesToRemove` that are not shown in the cached record
            return BAD_VALUE;
        }
        mCapturePresetDevicesRole[audioSource][role] = remainingDevices;
        if (mCapturePresetDevicesRole[audioSource][role].empty()) {
        mCapturePresetDevicesRoleMap[audioSourceRole] = remainingDevices;
        if (mCapturePresetDevicesRoleMap[audioSourceRole].empty()) {
            // Remove the role when device list is empty
            mCapturePresetDevicesRole[audioSource].erase(role);
            mCapturePresetDevicesRoleMap.erase(audioSourceRole);
        }
    } break;
    case DEVICE_ROLE_NONE:
@@ -543,63 +565,21 @@ status_t EngineBase::doRemoveDevicesRoleForCapturePreset(audio_source_t audioSou
status_t EngineBase::clearDevicesRoleForCapturePreset(audio_source_t audioSource,
                                                      device_role_t role)
{
    // verify if the audio source is valid
    if (!audio_is_valid_audio_source(audioSource)) {
        ALOGE("%s unknown audio source %u", __func__, audioSource);
    }

    switch (role) {
    case DEVICE_ROLE_PREFERRED:
        if (mCapturePresetDevicesRole.count(audioSource) == 0 ||
                mCapturePresetDevicesRole[audioSource].erase(role) == 0) {
            // no preferred device for the given audio source
            return NAME_NOT_FOUND;
        }
        break;
    case DEVICE_ROLE_DISABLED:
        // TODO: support remove devices role as disabled for strategy.
        ALOGI("%s no implemented for role as %d", __func__, role);
        break;
    case DEVICE_ROLE_NONE:
        // Intentionally fall-through as it makes no sense to remove devices with
        // role as DEVICE_ROLE_NONE for a strategy
    default:
        ALOGE("%s invalid role %d", __func__, role);
        return BAD_VALUE;
    }
    return NO_ERROR;
    std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
        return audio_is_valid_audio_source(audioSource);
    };
    return removeAllDevicesRoleForT(
            mCapturePresetDevicesRoleMap, audioSource, role, "audio source" /*logStr*/, p);
}

status_t EngineBase::getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
        device_role_t role, AudioDeviceTypeAddrVector &devices) const
{
    // verify if the audio source is valid
    if (!audio_is_valid_audio_source(audioSource)) {
        ALOGE("%s unknown audio source %u", __func__, audioSource);
        return BAD_VALUE;
    }

    switch (role) {
    case DEVICE_ROLE_PREFERRED:
    case DEVICE_ROLE_DISABLED: {
        if (mCapturePresetDevicesRole.count(audioSource) == 0) {
            return NAME_NOT_FOUND;
        }
        auto devIt = mCapturePresetDevicesRole.at(audioSource).find(role);
        if (devIt == mCapturePresetDevicesRole.at(audioSource).end()) {
            ALOGV("%s no devices role(%d) for capture preset %u", __func__, role, audioSource);
            return NAME_NOT_FOUND;
        }

        devices = devIt->second;
    } break;
    case DEVICE_ROLE_NONE:
        // Intentionally fall-through as the DEVICE_ROLE_NONE is never set
    default:
        ALOGE("%s invalid role %d", __func__, role);
        return BAD_VALUE;
    }
    return NO_ERROR;
    std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
        return audio_is_valid_audio_source(audioSource);
    };
    return getDevicesRoleForT(
            mCapturePresetDevicesRoleMap, audioSource, role, devices, "audio source" /*logStr*/, p);
}

status_t EngineBase::getMediaDevicesForRole(device_role_t role,
@@ -641,10 +621,22 @@ DeviceVector EngineBase::getActiveMediaDevices(const DeviceVector& availableDevi
    return activeDevices;
}

void EngineBase::dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const
{
    dst->appendFormat("\n%*sDevice role per capture preset dump:", spaces, "");
    for (const auto& [capturePresetRolePair, devices] : mCapturePresetDevicesRoleMap) {
        dst->appendFormat("\n%*sCapture preset(%u) Device Role(%u) Devices(%s)", spaces + 2, "",
                capturePresetRolePair.first, capturePresetRolePair.second,
                dumpAudioDeviceTypeAddrVector(devices, true /*includeSensitiveInfo*/).c_str());
    }
    dst->appendFormat("\n");
}

void EngineBase::dump(String8 *dst) const
{
    mProductStrategies.dump(dst, 2);
    mProductStrategyPreferredDevices.dump(dst, 2);
    dumpProductStrategyDevicesRoleMap(mProductStrategyDeviceRoleMap, dst, 2);
    dumpCapturePresetDevicesRoleMap(dst, 2);
    mVolumeGroups.dump(dst, 2);
}

+9 −8
Original line number Diff line number Diff line
@@ -320,14 +320,15 @@ void ProductStrategyMap::dump(String8 *dst, int spaces) const
    }
}

void ProductStrategyPreferredRoutingMap::dump(android::String8* dst, int spaces) const {
    dst->appendFormat("\n%*sPreferred devices per product strategy dump:", spaces, "");
    for (const auto& iter : *this) {
        dst->appendFormat("\n%*sStrategy %u %s",
                          spaces + 2, "",
                          (uint32_t) iter.first,
                          dumpAudioDeviceTypeAddrVector(iter.second, true /*includeSensitiveInfo*/)
                                  .c_str());
void dumpProductStrategyDevicesRoleMap(
        const ProductStrategyDevicesRoleMap& productStrategyDeviceRoleMap,
        String8 *dst,
        int spaces) {
    dst->appendFormat("\n%*sDevice role per product strategy dump:", spaces, "");
    for (const auto& [strategyRolePair, devices] : productStrategyDeviceRoleMap) {
        dst->appendFormat("\n%*sStrategy(%u) Device Role(%u) Devices(%s)", spaces + 2, "",
                strategyRolePair.first, strategyRolePair.second,
                dumpAudioDeviceTypeAddrVector(devices, true /*includeSensitiveInfo*/).c_str());
    }
    dst->appendFormat("\n");
}
+3 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#pragma once

#include <utility>

#include <AudioPolicyManagerObserver.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
@@ -35,7 +37,7 @@ using DeviceStrategyMap = std::map<product_strategy_t, DeviceVector>;
using StrategyVector = std::vector<product_strategy_t>;
using VolumeGroupVector = std::vector<volume_group_t>;
using CapturePresetDevicesRoleMap =
        std::map<audio_source_t, std::map<device_role_t, AudioDeviceTypeAddrVector>>;
        std::map<std::pair<audio_source_t, device_role_t>, AudioDeviceTypeAddrVector>;

/**
 * This interface is dedicated to the policy manager that a Policy Engine shall implement.