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

Commit 750b9e88 authored by Oscar Azucena's avatar Oscar Azucena Committed by Automerger Merge Worker
Browse files

Merge "Update Default AudioControl AIDL HAL for version 2" into tm-dev am: 65a25dd9

parents 742bb019 65a25dd9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -29,8 +29,9 @@ cc_binary {
    vendor: true,
    shared_libs: [
        "android.hardware.audio.common@7.0-enums",
        "android.hardware.audio.common-V1-ndk",
        "android.frameworks.automotive.powerpolicy-V1-ndk",
        "android.hardware.automotive.audiocontrol-V1-ndk",
        "android.hardware.automotive.audiocontrol-V2-ndk",
        "libbase",
        "libbinder_ndk",
        "libcutils",
+251 −3
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
#include <android_audio_policy_configuration_V7_0-enums.h>
#include <private/android_filesystem_config.h>

#include <numeric>

#include <stdio.h>

namespace aidl::android::hardware::automotive::audiocontrol {
@@ -147,6 +149,47 @@ ndk::ScopedAStatus AudioControl::onDevicesToMuteChange(
    return ndk::ScopedAStatus::ok();
}

template <typename aidl_type>
static inline std::string toString(const std::vector<aidl_type>& in_values) {
    return std::accumulate(std::begin(in_values), std::end(in_values), std::string{},
                           [](std::string& ls, const aidl_type& rs) {
                               return ls += (ls.empty() ? "" : ",") + rs.toString();
                           });
}
template <typename aidl_enum_type>
static inline std::string toEnumString(const std::vector<aidl_enum_type>& in_values) {
    return std::accumulate(std::begin(in_values), std::end(in_values), std::string{},
                           [](std::string& ls, const aidl_enum_type& rs) {
                               return ls += (ls.empty() ? "" : ",") + toString(rs);
                           });
}

ndk::ScopedAStatus AudioControl::onAudioFocusChangeWithMetaData(
        const audiohalcommon::PlaybackTrackMetadata& in_playbackMetaData, int32_t in_zoneId,
        AudioFocusChange in_focusChange) {
    LOG(INFO) << "Focus changed: " << toString(in_focusChange).c_str() << " for metadata "
              << in_playbackMetaData.toString().c_str() << " in zone " << in_zoneId;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus AudioControl::setAudioDeviceGainsChanged(
        const std::vector<Reasons>& in_reasons, const std::vector<AudioGainConfigInfo>& in_gains) {
    LOG(INFO) << "Audio Device Gains changed: resons:" << toEnumString(in_reasons).c_str()
              << " for devices: " << toString(in_gains).c_str();
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus AudioControl::registerGainCallback(
        const std::shared_ptr<IAudioGainCallback>& in_callback) {
    LOG(DEBUG) << ": " << __func__;
    if (in_callback) {
        std::atomic_store(&mAudioGainCallback, in_callback);
    } else {
        LOG(ERROR) << "Unexpected nullptr for audio gain callback resulting in no-op.";
    }
    return ndk::ScopedAStatus::ok();
}

binder_status_t AudioControl::dump(int fd, const char** args, uint32_t numArgs) {
    if (numArgs == 0) {
        return dumpsys(fd);
@@ -159,6 +202,12 @@ binder_status_t AudioControl::dump(int fd, const char** args, uint32_t numArgs)
        return cmdRequestFocus(fd, args, numArgs);
    } else if (EqualsIgnoreCase(option, "--abandon")) {
        return cmdAbandonFocus(fd, args, numArgs);
    } else if (EqualsIgnoreCase(option, "--requestFocusWithMetaData")) {
        return cmdRequestFocusWithMetaData(fd, args, numArgs);
    } else if (EqualsIgnoreCase(option, "--abandonFocusWithMetaData")) {
        return cmdAbandonFocusWithMetaData(fd, args, numArgs);
    } else if (EqualsIgnoreCase(option, "--audioGainCallback")) {
        return cmdOnAudioDeviceGainsChanged(fd, args, numArgs);
    } else {
        dprintf(fd, "Invalid option: %s\n", option.c_str());
        return STATUS_BAD_VALUE;
@@ -171,20 +220,49 @@ binder_status_t AudioControl::dumpsys(int fd) {
    } else {
        dprintf(fd, "Focus listener registered\n");
    }
    dprintf(fd, "AudioGainCallback %sregistered\n", (mAudioGainCallback == nullptr ? "NOT " : ""));
    return STATUS_OK;
}

binder_status_t AudioControl::cmdHelp(int fd) const {
    dprintf(fd, "Usage: \n\n");
    dprintf(fd, "[no args]: dumps focus listener status\n");
    dprintf(fd, "[no args]: dumps focus listener / gain callback registered status\n");
    dprintf(fd, "--help: shows this help\n");
    dprintf(fd,
            "--request <USAGE> <ZONE_ID> <FOCUS_GAIN>: requests audio focus for specified "
            "usage (string), audio zone ID (int), and focus gain type (int)\n");
            "usage (string), audio zone ID (int), and focus gain type (int)\n"
            "Deprecated, use MetaData instead\n");
    dprintf(fd,
            "--abandon <USAGE> <ZONE_ID>: abandons audio focus for specified usage (string) and "
            "audio zone ID (int)\n");
            "audio zone ID (int)\n"
            "Deprecated, use MetaData instead\n");
    dprintf(fd, "See audio_policy_configuration.xsd for valid AudioUsage values.\n");

    dprintf(fd,
            "--requestFocusWithMetaData <METADATA> <ZONE_ID> <FOCUS_GAIN>: "
            "requests audio focus for specified metadata, audio zone ID (int), "
            "and focus gain type (int)\n");
    dprintf(fd,
            "--abandonFocusWithMetaData <METADATA> <ZONE_ID>: "
            "abandons audio focus for specified metadata and audio zone ID (int)\n");
    dprintf(fd,
            "--audioGainCallback <ZONE_ID> <REASON_1>[,<REASON_N> ...]"
            "<DEVICE_ADDRESS_1> <GAIN_INDEX_1> [<DEVICE_ADDRESS_N> <GAIN_INDEX_N> ...]: fire audio "
            "gain callback for audio zone ID (int), the given reasons (csv int) for given pairs "
            "of device address (string) and gain index (int) \n");

    dprintf(fd,
            "Note on <METADATA>: <USAGE,CONTENT_TYPE[,TAGS]>  specified as where (int)usage, "
            "(int)content type and tags (string)string)\n");
    dprintf(fd,
            "See android/media/audio/common/AudioUsageType.aidl for valid AudioUsage values.\n");
    dprintf(fd,
            "See android/media/audio/common/AudioContentType.aidl for valid AudioContentType "
            "values.\n");
    dprintf(fd,
            "Tags are optional. If provided, it must follow the <key>=<value> pattern, where the "
            "value is namespaced (for example com.google.strategy=VR).\n");

    return STATUS_OK;
}

@@ -266,4 +344,174 @@ binder_status_t AudioControl::cmdAbandonFocus(int fd, const char** args, uint32_
    return STATUS_OK;
}

binder_status_t AudioControl::parseMetaData(int fd, const std::string& metadataLiteral,
                                            audiohalcommon::PlaybackTrackMetadata& trackMetadata) {
    std::stringstream csvMetaData(metadataLiteral);
    std::vector<std::string> splitMetaData;
    std::string attribute;
    while (getline(csvMetaData, attribute, ',')) {
        splitMetaData.push_back(attribute);
    }
    if (splitMetaData.size() != 2 && splitMetaData.size() != 3) {
        dprintf(fd,
                "Invalid metadata: %s, please provide <METADATA> as <USAGE,CONTENT_TYPE[,TAGS]> "
                "where (int)usage, (int)content type and tags (string)string)\n",
                metadataLiteral.c_str());
        return STATUS_BAD_VALUE;
    }
    int usage;
    if (!safelyParseInt(splitMetaData[0], &usage)) {
        dprintf(fd, "Non-integer usage provided with request: %s\n", splitMetaData[0].c_str());
        return STATUS_BAD_VALUE;
    }
    int contentType;
    if (!safelyParseInt(splitMetaData[1], &contentType)) {
        dprintf(fd, "Non-integer content type provided with request: %s\n",
                splitMetaData[1].c_str());
        return STATUS_BAD_VALUE;
    }
    const std::string tags = (splitMetaData.size() == 3 ? splitMetaData[2] : "");

    trackMetadata = {.usage = static_cast<audiomediacommon::AudioUsage>(usage),
                     .contentType = static_cast<audiomediacommon::AudioContentType>(contentType),
                     .tags = {tags}};
    return STATUS_OK;
}

binder_status_t AudioControl::cmdRequestFocusWithMetaData(int fd, const char** args,
                                                          uint32_t numArgs) {
    if (!checkCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if (numArgs != 4) {
        dprintf(fd,
                "Invalid number of arguments: please provide:\n"
                "--requestFocusWithMetaData <METADATA> <ZONE_ID> <FOCUS_GAIN>: "
                "requests audio focus for specified metadata, audio zone ID (int), "
                "and focus gain type (int)\n");
        return STATUS_BAD_VALUE;
    }
    std::string metadataLiteral = std::string(args[1]);
    audiohalcommon::PlaybackTrackMetadata trackMetadata{};
    auto status = parseMetaData(fd, metadataLiteral, trackMetadata);
    if (status != STATUS_OK) {
        return status;
    }

    int zoneId;
    if (!safelyParseInt(std::string(args[2]), &zoneId)) {
        dprintf(fd, "Non-integer zoneId provided with request: %s\n", std::string(args[2]).c_str());
        return STATUS_BAD_VALUE;
    }

    int focusGainValue;
    if (!safelyParseInt(std::string(args[3]), &focusGainValue)) {
        dprintf(fd, "Non-integer focusGain provided with request: %s\n",
                std::string(args[3]).c_str());
        return STATUS_BAD_VALUE;
    }
    AudioFocusChange focusGain = AudioFocusChange(focusGainValue);

    if (mFocusListener == nullptr) {
        dprintf(fd, "Unable to request focus - no focus listener registered\n");
        return STATUS_BAD_VALUE;
    }
    mFocusListener->requestAudioFocusWithMetaData(trackMetadata, zoneId, focusGain);
    dprintf(fd, "Requested focus for metadata %s, zoneId %d, and focusGain %d\n",
            trackMetadata.toString().c_str(), zoneId, focusGain);
    return STATUS_OK;
}

binder_status_t AudioControl::cmdAbandonFocusWithMetaData(int fd, const char** args,
                                                          uint32_t numArgs) {
    if (!checkCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if (numArgs != 3) {
        dprintf(fd,
                "Invalid number of arguments: please provide:\n"
                "--abandonFocusWithMetaData <METADATA> <ZONE_ID>: "
                "abandons audio focus for specified metadata and audio zone ID (int)\n");
        return STATUS_BAD_VALUE;
    }
    std::string metadataLiteral = std::string(args[1]);
    audiohalcommon::PlaybackTrackMetadata trackMetadata{};
    auto status = parseMetaData(fd, metadataLiteral, trackMetadata);
    if (status != STATUS_OK) {
        return status;
    }
    int zoneId;
    if (!safelyParseInt(std::string(args[2]), &zoneId)) {
        dprintf(fd, "Non-integer zoneId provided with request: %s\n", std::string(args[2]).c_str());
        return STATUS_BAD_VALUE;
    }
    if (mFocusListener == nullptr) {
        dprintf(fd, "Unable to abandon focus - no focus listener registered\n");
        return STATUS_BAD_VALUE;
    }

    mFocusListener->abandonAudioFocusWithMetaData(trackMetadata, zoneId);
    dprintf(fd, "Abandoned focus for metadata %s and zoneId %d\n", trackMetadata.toString().c_str(),
            zoneId);
    return STATUS_OK;
}

binder_status_t AudioControl::cmdOnAudioDeviceGainsChanged(int fd, const char** args,
                                                           uint32_t numArgs) {
    if (!checkCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if ((numArgs + 1) % 2 != 0) {
        dprintf(fd,
                "Invalid number of arguments: please provide\n"
                "--audioGainCallback <ZONE_ID> <REASON_1>[,<REASON_N> ...]"
                "<DEVICE_ADDRESS_1> <GAIN_INDEX_1> [<DEVICE_ADDRESS_N> <GAIN_INDEX_N> ...]: "
                "fire audio gain callback for audio zone ID (int), "
                "with the given reasons (csv int) for given pairs of device address (string) "
                "and gain index (int) \n");
        return STATUS_BAD_VALUE;
    }
    int zoneId;
    if (!safelyParseInt(string(args[1]), &zoneId)) {
        dprintf(fd, "Non-integer zoneId provided with request: %s\n", std::string(args[1]).c_str());
        return STATUS_BAD_VALUE;
    }
    std::string reasonsLiteral = std::string(args[2]);
    std::stringstream csvReasonsLiteral(reasonsLiteral);
    std::vector<Reasons> reasons;
    std::string reasonLiteral;
    while (getline(csvReasonsLiteral, reasonLiteral, ',')) {
        int reason;
        if (!safelyParseInt(reasonLiteral, &reason)) {
            dprintf(fd, "Invalid Reason(s) provided %s\n", reasonLiteral.c_str());
            return STATUS_BAD_VALUE;
        }
        reasons.push_back(static_cast<Reasons>(reason));
    }

    std::vector<AudioGainConfigInfo> agcis{};
    for (uint32_t i = 3; i < numArgs; i += 2) {
        std::string deviceAddress = std::string(args[i]);
        int32_t index;
        if (!safelyParseInt(std::string(args[i + 1]), &index)) {
            dprintf(fd, "Non-integer index provided with request: %s\n",
                    std::string(args[i + 1]).c_str());
            return STATUS_BAD_VALUE;
        }
        AudioGainConfigInfo agci{zoneId, deviceAddress, index};
        agcis.push_back(agci);
    }
    if (mAudioGainCallback == nullptr) {
        dprintf(fd,
                "Unable to trig audio gain callback for reasons=%s and gains=%s\n"
                " - no audio gain callback registered\n",
                toEnumString(reasons).c_str(), toString(agcis).c_str());
        return STATUS_BAD_VALUE;
    }

    mAudioGainCallback->onAudioDeviceGainsChanged(reasons, agcis);
    dprintf(fd, "Fired audio gain callback for reasons=%s and gains=%s\n",
            toEnumString(reasons).c_str(), toString(agcis).c_str());
    return STATUS_OK;
}
}  // namespace aidl::android::hardware::automotive::audiocontrol
+30 −0
Original line number Diff line number Diff line
@@ -17,12 +17,20 @@
#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_AUDIOCONTROL_H

#include <aidl/android/hardware/automotive/audiocontrol/AudioFocusChange.h>
#include <aidl/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.h>
#include <aidl/android/hardware/automotive/audiocontrol/BnAudioControl.h>
#include <aidl/android/hardware/automotive/audiocontrol/DuckingInfo.h>
#include <aidl/android/hardware/automotive/audiocontrol/IAudioGainCallback.h>
#include <aidl/android/hardware/automotive/audiocontrol/MutingInfo.h>
#include <aidl/android/hardware/automotive/audiocontrol/Reasons.h>

#include <aidl/android/hardware/audio/common/PlaybackTrackMetadata.h>

namespace aidl::android::hardware::automotive::audiocontrol {

namespace audiohalcommon = ::aidl::android::hardware::audio::common;
namespace audiomediacommon = ::aidl::android::media::audio::common;

class AudioControl : public BnAudioControl {
  public:
    ndk::ScopedAStatus onAudioFocusChange(const std::string& in_usage, int32_t in_zoneId,
@@ -35,6 +43,15 @@ class AudioControl : public BnAudioControl {
            const std::shared_ptr<IFocusListener>& in_listener) override;
    ndk::ScopedAStatus setBalanceTowardRight(float in_value) override;
    ndk::ScopedAStatus setFadeTowardFront(float in_value) override;
    ndk::ScopedAStatus onAudioFocusChangeWithMetaData(
            const audiohalcommon::PlaybackTrackMetadata& in_playbackMetaData, int32_t in_zoneId,
            AudioFocusChange in_focusChange) override;
    ndk::ScopedAStatus setAudioDeviceGainsChanged(
            const std::vector<Reasons>& in_reasons,
            const std::vector<AudioGainConfigInfo>& in_gains) override;
    ndk::ScopedAStatus registerGainCallback(
            const std::shared_ptr<IAudioGainCallback>& in_callback) override;

    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;

  private:
@@ -44,9 +61,22 @@ class AudioControl : public BnAudioControl {
    // listener, then it should also include mutexes or make the listener atomic.
    std::shared_ptr<IFocusListener> mFocusListener;

    /**
     * @brief mAudioGainCallback will be used by this HAL instance to communicate e.g. with a single
     * instance of CarAudioService to report unexpected gain changed.
     */
    std::shared_ptr<IAudioGainCallback> mAudioGainCallback = nullptr;

    binder_status_t cmdHelp(int fd) const;
    binder_status_t cmdRequestFocus(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdAbandonFocus(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdRequestFocusWithMetaData(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdAbandonFocusWithMetaData(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdOnAudioDeviceGainsChanged(int fd, const char** args, uint32_t numArgs);

    binder_status_t parseMetaData(int fd, const std::string& metadataLiteral,
                                  audiohalcommon::PlaybackTrackMetadata& trackMetadata);

    binder_status_t dumpsys(int fd);
};

+1 −1
Original line number Diff line number Diff line
<manifest version="1.0" type="device">
<manifest version="2.0" type="device">
    <hal format="aidl">
        <name>android.hardware.automotive.audiocontrol</name>
        <fqname>IAudioControl/default</fqname>