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

Commit b7c5ddba authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "libaudiohal: mmap playback support" am: 88e189e8 am: ed2e7d7f am: ef4e1fd2

parents 20bdf7d8 ef4e1fd2
Loading
Loading
Loading
Loading
+105 −12
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
#include <android/binder_enums.h>
#include <binder/Enums.h>
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionUtil.h>
@@ -36,26 +38,30 @@
using aidl::android::aidl_utils::statusTFromBinderStatus;
using aidl::android::media::audio::common::AudioConfig;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioLatencyMode;
using aidl::android::media::audio::common::AudioMMapPolicy;
using aidl::android::media::audio::common::AudioMMapPolicyInfo;
using aidl::android::media::audio::common::AudioMMapPolicyType;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortDeviceExt;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioPortMixExt;
using aidl::android::media::audio::common::AudioPortMixExtUseCase;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::Float;
using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
using aidl::android::hardware::audio::common::RecordTrackMetadata;
using aidl::android::hardware::audio::core::AudioPatch;
using aidl::android::hardware::audio::core::IModule;
@@ -84,6 +90,75 @@ void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& con
    portConfig->format = config.base.format;
}

template<typename OutEnum, typename OutEnumRange, typename InEnum>
ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
    using InIntType = std::underlying_type_t<InEnum>;
    static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);

    InIntType inEnumIndex = static_cast<InIntType>(e);
    OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
    if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
        return ::android::base::unexpected(BAD_VALUE);
    }
    return outEnum;
}

template<typename NdkEnum, typename CppEnum>
ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum e) {
    return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), e);
}

template<typename CppEnum, typename NdkEnum>
ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum e) {
    return convertEnum<CppEnum>(::android::enum_range<CppEnum>(), e);
}

ConversionResult<android::media::audio::common::AudioDeviceAddress>
ndk2cpp_AudioDeviceAddress(const AudioDeviceAddress& ndk) {
    using CppTag = android::media::audio::common::AudioDeviceAddress::Tag;
    using NdkTag = AudioDeviceAddress::Tag;

    CppTag cppTag = VALUE_OR_RETURN(ndk2cpp_Enum<CppTag>(ndk.getTag()));

    switch (cppTag) {
        case CppTag::id:
            return android::media::audio::common::AudioDeviceAddress::make<CppTag::id>(
                    ndk.get<NdkTag::id>());
        case CppTag::mac:
            return android::media::audio::common::AudioDeviceAddress::make<CppTag::mac>(
                    ndk.get<NdkTag::mac>());
        case CppTag::ipv4:
            return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv4>(
                    ndk.get<NdkTag::ipv4>());
        case CppTag::ipv6:
            return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv6>(
                    ndk.get<NdkTag::ipv6>());
        case CppTag::alsa:
            return android::media::audio::common::AudioDeviceAddress::make<CppTag::alsa>(
                    ndk.get<NdkTag::alsa>());
    }

    return ::android::base::unexpected(BAD_VALUE);
}

ConversionResult<media::audio::common::AudioDevice> ndk2cpp_AudioDevice(const AudioDevice& ndk) {
    media::audio::common::AudioDevice cpp;
    cpp.type.type = VALUE_OR_RETURN(
            ndk2cpp_Enum<media::audio::common::AudioDeviceType>(ndk.type.type));
    cpp.type.connection = ndk.type.connection;
    cpp.address = VALUE_OR_RETURN(ndk2cpp_AudioDeviceAddress(ndk.address));
    return cpp;
}

ConversionResult<media::audio::common::AudioMMapPolicyInfo>
ndk2cpp_AudioMMapPolicyInfo(const AudioMMapPolicyInfo& ndk) {
    media::audio::common::AudioMMapPolicyInfo cpp;
    cpp.device = VALUE_OR_RETURN(ndk2cpp_AudioDevice(ndk.device));
    cpp.mmapPolicy = VALUE_OR_RETURN(
            ndk2cpp_Enum<media::audio::common::AudioMMapPolicy>(ndk.mmapPolicy));
    return cpp;
}

}  // namespace

status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
@@ -732,23 +807,41 @@ status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
}

status_t DeviceHalAidl::getMmapPolicyInfos(
        media::audio::common::AudioMMapPolicyType policyType __unused,
        std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
        media::audio::common::AudioMMapPolicyType policyType,
        std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
    TIME_CHECK();
    ALOGE("%s not implemented yet", __func__);
    AudioMMapPolicyType mmapPolicyType =
            VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));

    std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;

    if (status_t status = statusTFromBinderStatus(
            mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
        return status;
    }

    *policyInfos = VALUE_OR_RETURN_STATUS(
            convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
                mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
    return OK;
}

int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
    TIME_CHECK();
    ALOGE("%s not implemented yet", __func__);
    return OK;
    int32_t mixerBurstCount = 0;
    if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
        return mixerBurstCount;
    }
    return 0;
}

int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
    TIME_CHECK();
    ALOGE("%s not implemented yet", __func__);
    return OK;
    int32_t hardwareBurstMinUsec = 0;
    if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
        return hardwareBurstMinUsec;
    }
    return 0;
}

error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
@@ -764,7 +857,7 @@ status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
    TIME_CHECK();
    if (!mModule) return NO_INIT;
    return mModule->dump(fd, Args(args).args(), args.size());
};
}

int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
    TIME_CHECK();
+48 −10
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ using ::aidl::android::hardware::audio::core::IStreamCommon;
using ::aidl::android::hardware::audio::core::IStreamIn;
using ::aidl::android::hardware::audio::core::IStreamOut;
using ::aidl::android::hardware::audio::core::StreamDescriptor;
using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;

namespace android {
@@ -255,16 +256,23 @@ status_t StreamHalAidl::start() {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    ALOGE("%s not implemented yet", __func__);
    return OK;
    const auto state = getState();
    StreamDescriptor::Reply reply;
    if (state == StreamDescriptor::State::STANDBY) {
        if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true);
                status != OK) {
            return status;
        }
        return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), &reply, true);
    }

    return INVALID_OPERATION;
}

status_t StreamHalAidl::stop() {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    ALOGE("%s not implemented yet", __func__);
    return OK;
    return standby();
}

status_t StreamHalAidl::getLatency(uint32_t *latency) {
@@ -290,6 +298,20 @@ status_t StreamHalAidl::getObservablePosition(int64_t *frames, int64_t *timestam
    return OK;
}

status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp) {
    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
    if (!mStream) return NO_INIT;
    StreamDescriptor::Reply reply;
    // TODO: switch to updateCountersIfNeeded once we sort out mWorkerTid initialization
    if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), &reply, true);
            status != OK) {
        return status;
    }
    *frames = reply.hardware.frames;
    *timestamp = reply.hardware.timeNs;
    return OK;
}

status_t StreamHalAidl::getXruns(int32_t *frames) {
    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
    if (!mStream) return NO_INIT;
@@ -419,19 +441,35 @@ status_t StreamHalAidl::exit() {
}

status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
                                  struct audio_mmap_buffer_info *info __unused) {
                                         struct audio_mmap_buffer_info *info) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    ALOGE("%s not implemented yet", __func__);
    if (!mContext.isMmapped()) {
        return BAD_VALUE;
    }
    const MmapBufferDescriptor& bufferDescriptor = mContext.getMmapBufferDescriptor();
    info->shared_memory_fd = bufferDescriptor.sharedMemory.fd.get();
    info->buffer_size_frames = mContext.getBufferSizeFrames();
    info->burst_size_frames = bufferDescriptor.burstSizeFrames;
    info->flags = static_cast<audio_mmap_buffer_flag>(bufferDescriptor.flags);

    return OK;
}

status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position) {
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    ALOGE("%s not implemented yet", __func__);
    if (!mContext.isMmapped()) {
        return BAD_VALUE;
    }
    int64_t aidlPosition = 0, aidlTimestamp = 0;
    if (status_t status = getHardwarePosition(&aidlPosition, &aidlTimestamp); status != OK) {
        return status;
    }

    position->time_nanoseconds = aidlTimestamp;
    position->position_frames = static_cast<int32_t>(aidlPosition);
    return OK;
}

+33 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <aidl/android/hardware/audio/core/BpStreamCommon.h>
#include <aidl/android/hardware/audio/core/BpStreamIn.h>
#include <aidl/android/hardware/audio/core/BpStreamOut.h>
#include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h>
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
@@ -34,6 +35,7 @@
#include "StreamPowerLog.h"

using ::aidl::android::hardware::audio::common::AudioOffloadMetadata;
using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;

namespace android {

@@ -47,21 +49,25 @@ class StreamContextAidl {
            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;

    explicit StreamContextAidl(
            const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
            ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
            bool isAsynchronous)
        : mFrameSizeBytes(descriptor.frameSizeBytes),
          mCommandMQ(new CommandMQ(descriptor.command)),
          mReplyMQ(new ReplyMQ(descriptor.reply)),
          mBufferSizeFrames(descriptor.bufferSizeFrames),
          mDataMQ(maybeCreateDataMQ(descriptor)),
          mIsAsynchronous(isAsynchronous) {}
          mIsAsynchronous(isAsynchronous),
          mIsMmapped(isMmapped(descriptor)),
          mMmapBufferDescriptor(maybeGetMmapBuffer(descriptor)) {}
    StreamContextAidl(StreamContextAidl&& other) :
            mFrameSizeBytes(other.mFrameSizeBytes),
            mCommandMQ(std::move(other.mCommandMQ)),
            mReplyMQ(std::move(other.mReplyMQ)),
            mBufferSizeFrames(other.mBufferSizeFrames),
            mDataMQ(std::move(other.mDataMQ)),
            mIsAsynchronous(other.mIsAsynchronous) {}
            mIsAsynchronous(other.mIsAsynchronous),
            mIsMmapped(other.mIsMmapped),
            mMmapBufferDescriptor(std::move(other.mMmapBufferDescriptor)) {}
    StreamContextAidl& operator=(StreamContextAidl&& other) {
        mFrameSizeBytes = other.mFrameSizeBytes;
        mCommandMQ = std::move(other.mCommandMQ);
@@ -69,16 +75,19 @@ class StreamContextAidl {
        mBufferSizeFrames = other.mBufferSizeFrames;
        mDataMQ = std::move(other.mDataMQ);
        mIsAsynchronous = other.mIsAsynchronous;
        mIsMmapped = other.mIsMmapped;
        mMmapBufferDescriptor = std::move(other.mMmapBufferDescriptor);
        return *this;
    }
    bool isValid() const {
        return mFrameSizeBytes != 0 &&
                mCommandMQ != nullptr && mCommandMQ->isValid() &&
                mReplyMQ != nullptr && mReplyMQ->isValid() &&
                (mDataMQ != nullptr || (
                (mDataMQ == nullptr || (
                        mDataMQ->isValid() &&
                        mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() >=
                        mFrameSizeBytes * mBufferSizeFrames));
                        mFrameSizeBytes * mBufferSizeFrames)) &&
                (!mIsMmapped || mMmapBufferDescriptor.sharedMemory.fd.get() >= 0);
    }
    size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
    size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
@@ -87,6 +96,8 @@ class StreamContextAidl {
    size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
    ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
    bool isAsynchronous() const { return mIsAsynchronous; }
    bool isMmapped() const { return mIsMmapped; }
    const MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; }

  private:
    static std::unique_ptr<DataMQ> maybeCreateDataMQ(
@@ -97,6 +108,19 @@ class StreamContextAidl {
        }
        return nullptr;
    }
    static bool isMmapped(
            const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
        using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
        return descriptor.audio.getTag() == Tag::mmap;
    }
    static MmapBufferDescriptor maybeGetMmapBuffer(
            ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
        using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
        if (descriptor.audio.getTag() == Tag::mmap) {
            return std::move(descriptor.audio.get<Tag::mmap>());
        }
        return {};
    }

    size_t mFrameSizeBytes;
    std::unique_ptr<CommandMQ> mCommandMQ;
@@ -104,6 +128,8 @@ class StreamContextAidl {
    size_t mBufferSizeFrames;
    std::unique_ptr<DataMQ> mDataMQ;
    bool mIsAsynchronous;
    bool mIsMmapped;
    MmapBufferDescriptor mMmapBufferDescriptor;
};

class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
@@ -181,6 +207,8 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper

    status_t getObservablePosition(int64_t *frames, int64_t *timestamp);

    status_t getHardwarePosition(int64_t *frames, int64_t *timestamp);

    status_t getXruns(int32_t *frames);

    status_t transfer(void *buffer, size_t bytes, size_t *transferred);