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

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

Merge "Clear up bit mask usage in audio policy."

parents b9c62a55 9a3361e4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ cc_library_shared {
    vendor_available: true,

    srcs: [
        "AudioContainers.cpp",
        "AudioGain.cpp",
        "AudioPort.cpp",
        "AudioProfile.cpp",
+86 −0
Original line number Diff line number Diff line
/*
 * 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
+69 −0
Original line number Diff line number Diff line
@@ -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
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
cc_library_headers {
    name: "libaudiopolicycommon",
    header_libs: [
        "libaudiofoundation_headers",
    ],
    export_include_dirs: ["include"],
}
+36 −23
Original line number Diff line number Diff line
@@ -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:
Loading