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

Commit 872d5453 authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Automerger Merge Worker
Browse files

Merge changes from topic "fix-b-274456992-mmap-status" into main am: 5e9fcfa5

parents 245d3be0 5e9fcfa5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ cc_library {
        "stub/ApeHeader.cpp",
        "stub/DriverStubImpl.cpp",
        "stub/ModuleStub.cpp",
        "stub/StreamMmapStub.cpp",
        "stub/StreamOffloadStub.cpp",
        "stub/StreamStub.cpp",
        "usb/ModuleUsb.cpp",
+47 −9
Original line number Diff line number Diff line
@@ -21,18 +21,23 @@
#include <android-base/logging.h>

#include "core-impl/ModulePrimary.h"
#include "core-impl/StreamMmapStub.h"
#include "core-impl/StreamOffloadStub.h"
#include "core-impl/StreamPrimary.h"
#include "core-impl/Telephony.h"

using aidl::android::hardware::audio::common::areAllBitPositionFlagsSet;
using aidl::android::hardware::audio::common::hasMmapFlag;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::hardware::audio::core::StreamDescriptor;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOffloadInfo;
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::AudioPortExt;
using aidl::android::media::audio::common::MicrophoneInfo;

namespace aidl::android::hardware::audio::core {
@@ -62,6 +67,11 @@ ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context,
                                                    const SinkMetadata& sinkMetadata,
                                                    const std::vector<MicrophoneInfo>& microphones,
                                                    std::shared_ptr<StreamIn>* result) {
    if (context.isMmap()) {
        // "Stub" is used because there is no support for MMAP audio I/O on CVD.
        return createStreamInstance<StreamInMmapStub>(result, std::move(context), sinkMetadata,
                                                      microphones);
    }
    return createStreamInstance<StreamInPrimary>(result, std::move(context), sinkMetadata,
                                                 microphones);
}
@@ -69,26 +79,54 @@ ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context,
ndk::ScopedAStatus ModulePrimary::createOutputStream(
        StreamContext&& context, const SourceMetadata& sourceMetadata,
        const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
    if (!areAllBitPositionFlagsSet(
    if (context.isMmap()) {
        // "Stub" is used because there is no support for MMAP audio I/O on CVD.
        return createStreamInstance<StreamOutMmapStub>(result, std::move(context), sourceMetadata,
                                                       offloadInfo);
    } else if (areAllBitPositionFlagsSet(
                       context.getFlags().get<AudioIoFlags::output>(),
                       {AudioOutputFlags::COMPRESS_OFFLOAD, AudioOutputFlags::NON_BLOCKING})) {
        return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata,
                                                      offloadInfo);
    } else {
        // "Stub" is used because there is no actual decoder. The stream just
        // extracts the clip duration from the media file header and simulates
        // playback over time.
        return createStreamInstance<StreamOutOffloadStub>(result, std::move(context),
                                                          sourceMetadata, offloadInfo);
    }
    return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata,
                                                  offloadInfo);
}

ndk::ScopedAStatus ModulePrimary::createMmapBuffer(const AudioPortConfig& portConfig,
                                                   int32_t bufferSizeFrames, int32_t frameSizeBytes,
                                                   MmapBufferDescriptor* desc) {
    const size_t bufferSizeBytes = static_cast<size_t>(bufferSizeFrames) * frameSizeBytes;
    // The actual mmap buffer for I/O is created after the stream exits standby, via
    // 'IStreamCommon.createMmapBuffer'. But we must return a valid file descriptor here because
    // 'MmapBufferDescriptor' can not contain a "null" fd.
    const std::string regionName =
            std::string("mmap-sim-o-") +
            std::to_string(portConfig.ext.get<AudioPortExt::Tag::mix>().handle);
    int fd = ashmem_create_region(regionName.c_str(), bufferSizeBytes);
    if (fd < 0) {
        PLOG(ERROR) << __func__ << ": failed to create shared memory region of " << bufferSizeBytes
                    << " bytes";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    desc->sharedMemory.fd = ndk::ScopedFileDescriptor(fd);
    desc->sharedMemory.size = bufferSizeBytes;
    desc->burstSizeFrames = bufferSizeFrames / 2;
    desc->flags = 0;
    LOG(DEBUG) << __func__ << ": " << desc->toString();
    return ndk::ScopedAStatus::ok();
}

int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig&) {
int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig& portConfig) {
    static constexpr int32_t kLowLatencyMs = 5;
    // 85 ms is chosen considering 4096 frames @ 48 kHz. This is the value which allows
    // the virtual Android device implementation to pass CTS. Hardware implementations
    // should have significantly lower latency.
    static constexpr int32_t kLatencyMs = 85;
    return kLatencyMs;
    static constexpr int32_t kStandardLatencyMs = 85;
    return hasMmapFlag(portConfig.flags.value()) ? kLowLatencyMs : kStandardLatencyMs;
}

}  // namespace aidl::android::hardware::audio::core
+3 −0
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ class ModulePrimary final : public Module {
            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
                    offloadInfo,
            std::shared_ptr<StreamOut>* result) override;
    ndk::ScopedAStatus createMmapBuffer(
            const ::aidl::android::media::audio::common::AudioPortConfig& portConfig,
            int32_t bufferSizeFrames, int32_t frameSizeBytes, MmapBufferDescriptor* desc) override;
    int32_t getNominalLatencyMs(
            const ::aidl::android::media::audio::common::AudioPortConfig& portConfig) override;

+132 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.
 */

#pragma once

#include <mutex>
#include <string>

#include "core-impl/DriverStubImpl.h"
#include "core-impl/Stream.h"

namespace aidl::android::hardware::audio::core {

namespace mmap {

struct DspSimulatorState {
    const bool isInput;
    const int sampleRate;
    const int frameSizeBytes;
    const size_t bufferSizeBytes;
    std::mutex lock;
    // The lock is also used to prevent un-mapping while the memory is in use.
    uint8_t* sharedMemory GUARDED_BY(lock) = nullptr;
    StreamDescriptor::Position mmapPos GUARDED_BY(lock);
};

class DspSimulatorLogic : public ::android::hardware::audio::common::StreamLogic {
  protected:
    explicit DspSimulatorLogic(DspSimulatorState& sharedState) : mSharedState(sharedState) {}
    std::string init() override;
    Status cycle() override;

  private:
    DspSimulatorState& mSharedState;
    uint32_t mCycleDurationUs = 0;
    uint8_t* mMemBegin = nullptr;
    uint8_t* mMemPos = nullptr;
    int64_t mLastFrames = 0;
};

class DspSimulatorWorker
    : public ::android::hardware::audio::common::StreamWorker<DspSimulatorLogic> {
  public:
    explicit DspSimulatorWorker(DspSimulatorState& sharedState)
        : ::android::hardware::audio::common::StreamWorker<DspSimulatorLogic>(sharedState) {}
};

}  // namespace mmap

class DriverMmapStubImpl : public DriverStubImpl {
  public:
    explicit DriverMmapStubImpl(const StreamContext& context);
    ::android::status_t init(DriverCallbackInterface* callback) override;
    ::android::status_t drain(StreamDescriptor::DrainMode drainMode) override;
    ::android::status_t pause() override;
    ::android::status_t start() override;
    ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
                                 int32_t* latencyMs) override;
    void shutdown() override;
    ::android::status_t refinePosition(StreamDescriptor::Position* position) override;
    ::android::status_t getMmapPositionAndLatency(StreamDescriptor::Position* position,
                                                  int32_t* latency) override;

  protected:
    ::android::status_t initSharedMemory(int ashmemFd);

  private:
    ::android::status_t releaseSharedMemory() REQUIRES(mState.lock);
    ::android::status_t startWorkerIfNeeded();

    mmap::DspSimulatorState mState;
    mmap::DspSimulatorWorker mDspWorker;
    bool mDspWorkerStarted = false;
};

class StreamMmapStub : public StreamCommonImpl, public DriverMmapStubImpl {
  public:
    static const std::string kCreateMmapBufferName;

    StreamMmapStub(StreamContext* context, const Metadata& metadata);
    ~StreamMmapStub();

    ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
                                           std::vector<VendorParameter>* _aidl_return) override;
    ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
                                           bool in_async) override;

  private:
    ndk::ScopedAStatus createMmapBuffer(MmapBufferDescriptor* desc);

    ndk::ScopedFileDescriptor mSharedMemoryFd;
};

class StreamInMmapStub final : public StreamIn, public StreamMmapStub {
  public:
    friend class ndk::SharedRefBase;
    StreamInMmapStub(
            StreamContext&& context,
            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);

  private:
    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
};

class StreamOutMmapStub final : public StreamOut, public StreamMmapStub {
  public:
    friend class ndk::SharedRefBase;
    StreamOutMmapStub(
            StreamContext&& context,
            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
                    offloadInfo);

  private:
    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
};

}  // namespace aidl::android::hardware::audio::core
+8 −3
Original line number Diff line number Diff line
@@ -19,12 +19,15 @@
#include <mutex>
#include <set>
#include <string>
#include <vector>

#include "core-impl/DriverStubImpl.h"
#include "core-impl/Stream.h"

namespace aidl::android::hardware::audio::core {

namespace offload {

struct DspSimulatorState {
    static constexpr int64_t kSkipBufferNotifyFrames = -1;

@@ -55,9 +58,11 @@ class DspSimulatorWorker
        : ::android::hardware::audio::common::StreamWorker<DspSimulatorLogic>(sharedState) {}
};

}  // namespace offload

class DriverOffloadStubImpl : public DriverStubImpl {
  public:
    DriverOffloadStubImpl(const StreamContext& context);
    explicit DriverOffloadStubImpl(const StreamContext& context);
    ::android::status_t init(DriverCallbackInterface* callback) override;
    ::android::status_t drain(StreamDescriptor::DrainMode drainMode) override;
    ::android::status_t flush() override;
@@ -71,8 +76,8 @@ class DriverOffloadStubImpl : public DriverStubImpl {
    ::android::status_t startWorkerIfNeeded();

    const int64_t mBufferNotifyFrames;
    DspSimulatorState mState;
    DspSimulatorWorker mDspWorker;
    offload::DspSimulatorState mState;
    offload::DspSimulatorWorker mDspWorker;
    bool mDspWorkerStarted = false;
};

Loading